001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.openjpa.jdbc.meta.strats;
020:
021: import java.lang.reflect.Modifier;
022: import java.sql.Types;
023: import java.util.HashMap;
024: import java.util.List;
025: import java.util.Map;
026: import java.util.TreeSet;
027:
028: import org.apache.openjpa.jdbc.kernel.JDBCStore;
029: import org.apache.openjpa.jdbc.meta.ClassMapping;
030: import org.apache.openjpa.jdbc.meta.Discriminator;
031: import org.apache.openjpa.jdbc.meta.DiscriminatorMappingInfo;
032: import org.apache.openjpa.jdbc.schema.Column;
033: import org.apache.openjpa.jdbc.schema.Schemas;
034: import org.apache.openjpa.lib.util.Localizer;
035: import org.apache.openjpa.meta.JavaTypes;
036: import org.apache.openjpa.util.MetaDataException;
037:
038: /**
039: * Maps metadata-given values to classes.
040: *
041: * @author Abe White
042: */
043: public class ValueMapDiscriminatorStrategy extends
044: InValueDiscriminatorStrategy {
045:
046: public static final String ALIAS = "value-map";
047:
048: private static final Localizer _loc = Localizer
049: .forPackage(ValueMapDiscriminatorStrategy.class);
050:
051: private Map _vals = null;
052:
053: public String getAlias() {
054: return ALIAS;
055: }
056:
057: protected int getJavaType() {
058: Object val = disc.getValue();
059: if (val != null && val != Discriminator.NULL)
060: return JavaTypes.getTypeCode(val.getClass());
061:
062: // if the user wants the type to be null, we need a jdbc-type
063: // on the column or an existing column to figure out the java type
064: DiscriminatorMappingInfo info = disc.getMappingInfo();
065: List cols = info.getColumns();
066: Column col = (cols.isEmpty()) ? null : (Column) cols.get(0);
067: if (col != null) {
068: if (col.getJavaType() != JavaTypes.OBJECT)
069: return col.getJavaType();
070: if (col.getType() != Types.OTHER)
071: return JavaTypes.getTypeCode(Schemas.getJavaType(col
072: .getType(), col.getSize(), col
073: .getDecimalDigits()));
074: }
075: return JavaTypes.STRING;
076: }
077:
078: protected Object getDiscriminatorValue(ClassMapping cls) {
079: Object val = cls.getDiscriminator().getValue();
080: return (val == Discriminator.NULL) ? null : val;
081: }
082:
083: protected Class getClass(Object val, JDBCStore store)
084: throws ClassNotFoundException {
085: if (_vals == null) {
086: ClassMapping cls = disc.getClassMapping();
087: ClassMapping[] subs = cls.getJoinablePCSubclassMappings();
088: Map map = new HashMap((int) ((subs.length + 1) * 1.33 + 1));
089: mapDiscriminatorValue(cls, map);
090: for (int i = 0; i < subs.length; i++)
091: mapDiscriminatorValue(subs[i], map);
092: _vals = map;
093: }
094:
095: String str = (val == null) ? null : val.toString();
096: Class cls = (Class) _vals.get(str);
097: if (cls != null)
098: return cls;
099: throw new ClassNotFoundException(_loc
100: .get(
101: "unknown-discrim-value",
102: new Object[] {
103: str,
104: disc.getClassMapping()
105: .getDescribedType().getName(),
106: new TreeSet(_vals.keySet()) })
107: .getMessage());
108: }
109:
110: /**
111: * Map the stringified version of the discriminator value of the given type.
112: */
113: private static void mapDiscriminatorValue(ClassMapping cls, Map map) {
114: // possible that some types will never be persisted and therefore
115: // can have no discriminator value
116: Object val = cls.getDiscriminator().getValue();
117: if (val == null)
118: return;
119:
120: String str = (val == Discriminator.NULL) ? null : val
121: .toString();
122: Class exist = (Class) map.get(str);
123: if (exist != null)
124: throw new MetaDataException(_loc.get("dup-discrim-value",
125: str, exist, cls));
126: map.put(str, cls.getDescribedType());
127: }
128:
129: public void map(boolean adapt) {
130: Object val = disc.getMappingInfo().getValue(disc, adapt);
131: if (val == null
132: && !Modifier.isAbstract(disc.getClassMapping()
133: .getDescribedType().getModifiers()))
134: throw new MetaDataException(_loc.get("no-discrim-value",
135: disc.getClassMapping()));
136:
137: // we set the value before mapping to use to calculate the template
138: // column's java type
139: disc.setValue(val);
140: super.map(adapt);
141: }
142: }
|