| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.openjpa.persistence.jdbc; |
| |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.ASSOC_OVERRIDE; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.ASSOC_OVERRIDES; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.ATTR_OVERRIDE; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.ATTR_OVERRIDES; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.CLASS_CRIT; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.COL; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.COLLECTION_TABLE; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.COLS; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.COLUMN_RESULT; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.CONTAINER_TABLE; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.DATASTORE_ID_COL; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.DISCRIM_COL; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.DISCRIM_STRAT; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.DISCRIM_VAL; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.EAGER_FETCH_MODE; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.ELEM_CLASS_CRIT; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.ELEM_COL; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.ELEM_COLS; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.ELEM_EMBEDDED_MAPPING; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.ELEM_FK; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.ELEM_INDEX; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.ELEM_JOIN_COL; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.ELEM_JOIN_COLS; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.ELEM_NONPOLY; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.ELEM_STRAT; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.EMBEDDED_MAPPING; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.ENTITY_RESULT; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.ENUMERATED; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.FIELD_RESULT; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.FK; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.INDEX; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.INHERITANCE; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.JOIN_COL; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.JOIN_COLS; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.JOIN_TABLE; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.KEY_CLASS_CRIT; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.KEY_COL; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.KEY_COLS; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.KEY_EMBEDDED_MAPPING; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.KEY_FK; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.KEY_INDEX; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.KEY_JOIN_COL; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.KEY_JOIN_COLS; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.KEY_NONPOLY; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.KEY_STRAT; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.MAPPING_OVERRIDE; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.MAPPING_OVERRIDES; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.MAP_KEY_COL; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.MAP_KEY_ENUMERATED; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.MAP_KEY_JOIN_COL; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.MAP_KEY_JOIN_COLS; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.MAP_KEY_TEMPORAL; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.NONPOLY; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.ORDER_COL; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.ORDER_COLUMN; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.PK_JOIN_COL; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.PK_JOIN_COLS; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.SECONDARY_TABLE; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.SECONDARY_TABLES; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.SQL_RESULT_SET_MAPPING; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.SQL_RESULT_SET_MAPPINGS; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.STRAT; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.SUBCLASS_FETCH_MODE; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.TABLE; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.TABLE_GEN; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.TEMPORAL; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.UNIQUE; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.VERSION_COL; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.VERSION_COLS; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.VERSION_STRAT; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.X_EMBEDDED_MAPPING; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.X_JOIN_COL; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.X_JOIN_COLS; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.X_MAPPING_OVERRIDE; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.X_MAPPING_OVERRIDES; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.X_SECONDARY_TABLE; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.X_SECONDARY_TABLES; |
| import static org.apache.openjpa.persistence.jdbc.MappingTag.X_TABLE; |
| |
| import java.lang.annotation.Annotation; |
| import java.lang.reflect.AnnotatedElement; |
| import java.lang.reflect.Modifier; |
| import java.security.AccessController; |
| import java.sql.Types; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.persistence.AssociationOverride; |
| import javax.persistence.AssociationOverrides; |
| import javax.persistence.AttributeOverride; |
| import javax.persistence.AttributeOverrides; |
| import javax.persistence.CollectionTable; |
| import javax.persistence.ColumnResult; |
| import javax.persistence.ConstructorResult; |
| import javax.persistence.DiscriminatorColumn; |
| import javax.persistence.DiscriminatorValue; |
| import javax.persistence.EntityResult; |
| import javax.persistence.EnumType; |
| import javax.persistence.Enumerated; |
| import javax.persistence.FieldResult; |
| import javax.persistence.Inheritance; |
| import javax.persistence.JoinColumn; |
| import javax.persistence.JoinColumns; |
| import javax.persistence.JoinTable; |
| import javax.persistence.MapKeyColumn; |
| import javax.persistence.MapKeyEnumerated; |
| import javax.persistence.MapKeyJoinColumn; |
| import javax.persistence.MapKeyJoinColumns; |
| import javax.persistence.MapKeyTemporal; |
| import javax.persistence.PrimaryKeyJoinColumn; |
| import javax.persistence.PrimaryKeyJoinColumns; |
| import javax.persistence.SecondaryTable; |
| import javax.persistence.SecondaryTables; |
| import javax.persistence.SqlResultSetMapping; |
| import javax.persistence.SqlResultSetMappings; |
| import javax.persistence.Table; |
| import javax.persistence.TableGenerator; |
| import javax.persistence.Temporal; |
| import javax.persistence.UniqueConstraint; |
| |
| import org.apache.openjpa.jdbc.conf.JDBCConfiguration; |
| import org.apache.openjpa.jdbc.identifier.DBIdentifier; |
| import org.apache.openjpa.jdbc.identifier.DBIdentifier.DBIdentifierType; |
| import org.apache.openjpa.jdbc.identifier.QualifiedDBIdentifier; |
| import org.apache.openjpa.jdbc.kernel.EagerFetchModes; |
| import org.apache.openjpa.jdbc.meta.ClassMapping; |
| import org.apache.openjpa.jdbc.meta.ClassMappingInfo; |
| import org.apache.openjpa.jdbc.meta.Discriminator; |
| import org.apache.openjpa.jdbc.meta.FieldMapping; |
| import org.apache.openjpa.jdbc.meta.FieldMappingInfo; |
| import org.apache.openjpa.jdbc.meta.MappingInfo; |
| import org.apache.openjpa.jdbc.meta.MappingRepository; |
| import org.apache.openjpa.jdbc.meta.QueryResultMapping; |
| import org.apache.openjpa.jdbc.meta.QueryResultMapping.PCResult; |
| import org.apache.openjpa.jdbc.meta.SequenceMapping; |
| import org.apache.openjpa.jdbc.meta.ValueMapping; |
| import org.apache.openjpa.jdbc.meta.ValueMappingInfo; |
| import org.apache.openjpa.jdbc.meta.strats.EnumValueHandler; |
| import org.apache.openjpa.jdbc.meta.strats.FlatClassStrategy; |
| import org.apache.openjpa.jdbc.meta.strats.FullClassStrategy; |
| import org.apache.openjpa.jdbc.meta.strats.VerticalClassStrategy; |
| import org.apache.openjpa.jdbc.schema.Column; |
| import org.apache.openjpa.jdbc.schema.Schemas; |
| import org.apache.openjpa.jdbc.schema.Unique; |
| import org.apache.openjpa.jdbc.sql.DBDictionary; |
| import org.apache.openjpa.lib.log.Log; |
| import org.apache.openjpa.lib.meta.SourceTracker; |
| import org.apache.openjpa.lib.util.J2DoPrivHelper; |
| import org.apache.openjpa.lib.util.Localizer; |
| import org.apache.openjpa.lib.util.StringUtil; |
| import org.apache.openjpa.meta.ClassMetaData; |
| import org.apache.openjpa.meta.FieldMetaData; |
| import org.apache.openjpa.meta.JavaTypes; |
| import org.apache.openjpa.meta.MetaDataContext; |
| import org.apache.openjpa.persistence.AnnotationPersistenceMetaDataParser; |
| import org.apache.openjpa.util.InternalException; |
| import org.apache.openjpa.util.MetaDataException; |
| import org.apache.openjpa.util.UnsupportedException; |
| import org.apache.openjpa.util.UserException; |
| |
| /** |
| * Persistence annotation mapping parser. |
| * |
| * @author Pinaki Poddar |
| * @author Steve Kim |
| * @author Abe White |
| */ |
| public class AnnotationPersistenceMappingParser |
| extends AnnotationPersistenceMetaDataParser { |
| |
| protected static final int TRUE = 1; |
| protected static final int FALSE = 2; |
| |
| private static final Localizer _loc = Localizer.forPackage |
| (AnnotationPersistenceMappingParser.class); |
| |
| private static final Map<Class<?>, MappingTag> _tags = |
| new HashMap<>(); |
| |
| private DBDictionary _dict; |
| |
| static { |
| _tags.put(AssociationOverride.class, ASSOC_OVERRIDE); |
| _tags.put(AssociationOverrides.class, ASSOC_OVERRIDES); |
| _tags.put(AttributeOverride.class, ATTR_OVERRIDE); |
| _tags.put(AttributeOverrides.class, ATTR_OVERRIDES); |
| _tags.put(javax.persistence.Column.class, COL); |
| _tags.put(ColumnResult.class, COLUMN_RESULT); |
| _tags.put(DiscriminatorColumn.class, DISCRIM_COL); |
| _tags.put(DiscriminatorValue.class, DISCRIM_VAL); |
| _tags.put(ElementColumn.class, ELEM_COL); |
| _tags.put(ElementColumns.class, ELEM_COLS); |
| _tags.put(ElementEmbeddedMapping.class, ELEM_EMBEDDED_MAPPING); |
| _tags.put(ElementStrategy.class, ELEM_STRAT); |
| _tags.put(EntityResult.class, ENTITY_RESULT); |
| _tags.put(Enumerated.class, ENUMERATED); |
| _tags.put(FieldResult.class, FIELD_RESULT); |
| _tags.put(Inheritance.class, INHERITANCE); |
| _tags.put(JoinColumn.class, JOIN_COL); |
| _tags.put(JoinColumns.class, JOIN_COLS); |
| _tags.put(JoinTable.class, JOIN_TABLE); |
| _tags.put(KeyColumn.class, KEY_COL); |
| _tags.put(KeyColumns.class, KEY_COLS); |
| _tags.put(KeyClassCriteria.class, KEY_CLASS_CRIT); |
| _tags.put(KeyEmbeddedMapping.class, KEY_EMBEDDED_MAPPING); |
| _tags.put(KeyForeignKey.class, KEY_FK); |
| _tags.put(KeyIndex.class, KEY_INDEX); |
| _tags.put(KeyJoinColumn.class, KEY_JOIN_COL); |
| _tags.put(KeyJoinColumns.class, KEY_JOIN_COLS); |
| _tags.put(KeyNonpolymorphic.class, KEY_NONPOLY); |
| _tags.put(KeyStrategy.class, KEY_STRAT); |
| _tags.put(MapKeyColumn.class, MAP_KEY_COL); |
| _tags.put(MapKeyEnumerated.class, MAP_KEY_ENUMERATED); |
| _tags.put(MapKeyJoinColumn.class, MAP_KEY_JOIN_COL); |
| _tags.put(MapKeyJoinColumns.class, MAP_KEY_JOIN_COLS); |
| _tags.put(MapKeyTemporal.class, MAP_KEY_TEMPORAL); |
| _tags.put(PrimaryKeyJoinColumn.class, PK_JOIN_COL); |
| _tags.put(PrimaryKeyJoinColumns.class, PK_JOIN_COLS); |
| _tags.put(SecondaryTable.class, SECONDARY_TABLE); |
| _tags.put(SecondaryTables.class, SECONDARY_TABLES); |
| _tags.put(SqlResultSetMapping.class, SQL_RESULT_SET_MAPPING); |
| _tags.put(SqlResultSetMappings.class, SQL_RESULT_SET_MAPPINGS); |
| _tags.put(Table.class, TABLE); |
| _tags.put(Temporal.class, TEMPORAL); |
| _tags.put(TableGenerator.class, TABLE_GEN); |
| _tags.put(ClassCriteria.class, CLASS_CRIT); |
| _tags.put(Columns.class, COLS); |
| _tags.put(ContainerTable.class, CONTAINER_TABLE); |
| _tags.put(CollectionTable.class, COLLECTION_TABLE); |
| _tags.put(DataStoreIdColumn.class, DATASTORE_ID_COL); |
| _tags.put(DiscriminatorStrategy.class, DISCRIM_STRAT); |
| _tags.put(EagerFetchMode.class, EAGER_FETCH_MODE); |
| _tags.put(ElementClassCriteria.class, ELEM_CLASS_CRIT); |
| _tags.put(ElementForeignKey.class, ELEM_FK); |
| _tags.put(ElementIndex.class, ELEM_INDEX); |
| _tags.put(ElementJoinColumn.class, ELEM_JOIN_COL); |
| _tags.put(ElementJoinColumns.class, ELEM_JOIN_COLS); |
| _tags.put(ElementNonpolymorphic.class, ELEM_NONPOLY); |
| _tags.put(EmbeddedMapping.class, EMBEDDED_MAPPING); |
| _tags.put(ForeignKey.class, FK); |
| _tags.put(Index.class, INDEX); |
| _tags.put(MappingOverride.class, MAPPING_OVERRIDE); |
| _tags.put(MappingOverrides.class, MAPPING_OVERRIDES); |
| _tags.put(Nonpolymorphic.class, NONPOLY); |
| _tags.put(OrderColumn.class, ORDER_COL); |
| _tags.put(javax.persistence.OrderColumn.class, ORDER_COLUMN); |
| _tags.put(Strategy.class, STRAT); |
| _tags.put(SubclassFetchMode.class, SUBCLASS_FETCH_MODE); |
| _tags.put(Unique.class, UNIQUE); |
| _tags.put(VersionColumn.class, VERSION_COL); |
| _tags.put(VersionColumns.class, VERSION_COLS); |
| _tags.put(VersionStrategy.class, VERSION_STRAT); |
| _tags.put(XEmbeddedMapping.class, X_EMBEDDED_MAPPING); |
| _tags.put(XJoinColumn.class, X_JOIN_COL); |
| _tags.put(XJoinColumns.class, X_JOIN_COLS); |
| _tags.put(XMappingOverride.class, X_MAPPING_OVERRIDE); |
| _tags.put(XMappingOverrides.class, X_MAPPING_OVERRIDES); |
| _tags.put(XSecondaryTable.class, X_SECONDARY_TABLE); |
| _tags.put(XSecondaryTables.class, X_SECONDARY_TABLES); |
| _tags.put(XTable.class, X_TABLE); |
| } |
| |
| public AnnotationPersistenceMappingParser(JDBCConfiguration conf) { |
| super(conf); |
| _dict = conf.getDBDictionaryInstance(); |
| } |
| |
| @Override |
| protected void parsePackageMappingAnnotations(Package pkg) { |
| MappingTag tag; |
| for (Annotation anno : pkg.getDeclaredAnnotations()) { |
| tag = _tags.get(anno.annotationType()); |
| if (tag == null) { |
| handleUnknownPackageMappingAnnotation(pkg, anno); |
| continue; |
| } |
| |
| switch (tag) { |
| case TABLE_GEN: |
| parseTableGenerator(pkg, (TableGenerator) anno); |
| break; |
| default: |
| throw new UnsupportedException(_loc.get("unsupported", pkg, |
| anno.toString())); |
| } |
| } |
| } |
| |
| /** |
| * Allow subclasses to handle unknown annotations. |
| */ |
| protected boolean handleUnknownPackageMappingAnnotation(Package pkg, |
| Annotation anno) { |
| return false; |
| } |
| |
| /** |
| * Parse @TableGenerator. |
| */ |
| private void parseTableGenerator(AnnotatedElement el, TableGenerator gen) { |
| String name = gen.name(); |
| if (StringUtil.isEmpty(name)) |
| throw new MetaDataException(_loc.get("no-gen-name", el)); |
| |
| Log log = getLog(); |
| if (log.isTraceEnabled()) |
| log.trace(_loc.get("parse-gen", name)); |
| |
| SequenceMapping meta = (SequenceMapping) getRepository(). |
| getCachedSequenceMetaData(name); |
| if (meta != null) { |
| if (log.isWarnEnabled()) |
| log.warn(_loc.get("dup-gen", name, el)); |
| return; |
| } |
| |
| meta = (SequenceMapping) getRepository().addSequenceMetaData(name); |
| meta.setSequencePlugin(SequenceMapping.IMPL_VALUE_TABLE); |
| meta.setTableIdentifier(toTableIdentifier(gen.schema(), gen.table())); |
| meta.setPrimaryKeyColumnIdentifier(DBIdentifier.newColumn(gen.pkColumnName(), delimit())); |
| meta.setSequenceColumnIdentifier(DBIdentifier.newColumn(gen.valueColumnName(),delimit())); |
| meta.setPrimaryKeyValue(gen.pkColumnValue()); |
| meta.setInitialValue(gen.initialValue()); |
| meta.setAllocate(gen.allocationSize()); |
| meta.setSource(getSourceFile(), (el instanceof Class) ? el : null, |
| SourceTracker.SRC_ANNOTATIONS); |
| |
| switch (gen.uniqueConstraints().length) { |
| case 0: |
| break; // nothing to do |
| case 1: |
| meta.setUniqueColumnsIdentifier(DBIdentifier.toArray(gen.uniqueConstraints()[0].columnNames(), |
| DBIdentifierType.COLUMN, delimit())); |
| meta.setUniqueConstraintIdentifier(DBIdentifier.newConstraint(gen.uniqueConstraints()[0].name(), |
| delimit())); |
| break; |
| default: |
| log.warn(_loc.get("unique-many-on-seq-unsupported", el, name)); |
| } |
| } |
| |
| @Override |
| protected void parseClassMappingAnnotations(ClassMetaData meta) { |
| ClassMapping cm = (ClassMapping) meta; |
| Class<?> cls = cm.getDescribedType(); |
| |
| MappingTag tag; |
| for (Annotation anno : cls.getDeclaredAnnotations()) { |
| tag = _tags.get(anno.annotationType()); |
| if (tag == null) { |
| handleUnknownClassMappingAnnotation(cm, anno); |
| continue; |
| } |
| |
| switch (tag) { |
| case ASSOC_OVERRIDE: |
| parseAssociationOverrides(cm, (AssociationOverride) anno); |
| break; |
| case ASSOC_OVERRIDES: |
| parseAssociationOverrides(cm, ((AssociationOverrides) anno). |
| value()); |
| break; |
| case ATTR_OVERRIDE: |
| parseAttributeOverrides(cm, (AttributeOverride) anno); |
| break; |
| case ATTR_OVERRIDES: |
| parseAttributeOverrides(cm, ((AttributeOverrides) anno). |
| value()); |
| break; |
| case DISCRIM_COL: |
| parseDiscriminatorColumn(cm, (DiscriminatorColumn) anno); |
| break; |
| case DISCRIM_VAL: |
| cm.getDiscriminator().getMappingInfo().setValue |
| (((DiscriminatorValue) anno).value()); |
| if (Modifier.isAbstract(cm.getDescribedType(). |
| getModifiers()) && getLog().isInfoEnabled()) { |
| getLog().info( |
| _loc.get("discriminator-on-abstract-class", cm |
| .getDescribedType().getName())); |
| } |
| break; |
| case INHERITANCE: |
| parseInheritance(cm, (Inheritance) anno); |
| break; |
| case PK_JOIN_COL: |
| parsePrimaryKeyJoinColumns(cm, (PrimaryKeyJoinColumn) anno); |
| break; |
| case PK_JOIN_COLS: |
| parsePrimaryKeyJoinColumns(cm, |
| ((PrimaryKeyJoinColumns) anno). |
| value()); |
| break; |
| case SECONDARY_TABLE: |
| parseSecondaryTables(cm, (SecondaryTable) anno); |
| break; |
| case SECONDARY_TABLES: |
| parseSecondaryTables(cm, ((SecondaryTables) anno).value()); |
| break; |
| case SQL_RESULT_SET_MAPPING: |
| parseSQLResultSetMappings(cm, (SqlResultSetMapping) anno); |
| break; |
| case SQL_RESULT_SET_MAPPINGS: |
| parseSQLResultSetMappings(cm, ((SqlResultSetMappings) anno). |
| value()); |
| break; |
| case TABLE: |
| parseTable(cm, (Table) anno); |
| break; |
| case TABLE_GEN: |
| parseTableGenerator(cls, (TableGenerator) anno); |
| break; |
| case DATASTORE_ID_COL: |
| parseDataStoreIdColumn(cm, (DataStoreIdColumn) anno); |
| break; |
| case DISCRIM_STRAT: |
| cm.getDiscriminator().getMappingInfo().setStrategy |
| (((DiscriminatorStrategy) anno).value()); |
| break; |
| case FK: |
| parseForeignKey(cm.getMappingInfo(), (ForeignKey) anno); |
| break; |
| case MAPPING_OVERRIDE: |
| parseMappingOverrides(cm, (MappingOverride) anno); |
| break; |
| case MAPPING_OVERRIDES: |
| parseMappingOverrides(cm, |
| ((MappingOverrides) anno).value()); |
| break; |
| case STRAT: |
| cm.getMappingInfo().setStrategy(((Strategy) anno).value()); |
| break; |
| case SUBCLASS_FETCH_MODE: |
| cm.setSubclassFetchMode(toEagerFetchModeConstant |
| (((SubclassFetchMode) anno).value())); |
| break; |
| case VERSION_COL: |
| parseVersionColumns(cm, (VersionColumn) anno); |
| break; |
| case VERSION_COLS: |
| parseVersionColumns(cm, ((VersionColumns) anno).value()); |
| break; |
| case VERSION_STRAT: |
| cm.getVersion().getMappingInfo().setStrategy |
| (((VersionStrategy) anno).value()); |
| break; |
| case X_MAPPING_OVERRIDE: |
| parseMappingOverrides(cm, (XMappingOverride) anno); |
| break; |
| case X_MAPPING_OVERRIDES: |
| parseMappingOverrides(cm, |
| ((XMappingOverrides) anno).value()); |
| break; |
| case X_TABLE: |
| case X_SECONDARY_TABLE: |
| case X_SECONDARY_TABLES: |
| // no break; not supported yet |
| default: |
| throw new UnsupportedException(_loc.get("unsupported", cm, |
| anno)); |
| } |
| } |
| } |
| |
| /** |
| * Allow subclasses to handle unknown annotations. |
| */ |
| protected boolean handleUnknownClassMappingAnnotation(ClassMapping cls, |
| Annotation anno) { |
| return false; |
| } |
| |
| /** |
| * Parse @AssociationOverride(s). |
| */ |
| private void parseAssociationOverrides(ClassMapping cm, |
| AssociationOverride... assocs) { |
| FieldMapping sup; |
| JoinColumn[] scols; |
| int unique; |
| List<Column> jcols; |
| JoinTable joinTbl; |
| for (AssociationOverride assoc : assocs) { |
| if (StringUtil.isEmpty(assoc.name())) |
| throw new MetaDataException(_loc.get("no-override-name", cm)); |
| sup = (FieldMapping) cm.getDefinedSuperclassField(assoc.name()); |
| if (sup == null) |
| sup = (FieldMapping) cm.addDefinedSuperclassField |
| (assoc.name(), Object.class, Object.class); |
| scols = assoc.joinColumns(); |
| joinTbl = assoc.joinTable(); |
| if ((scols == null || scols.length == 0) && joinTbl == null) |
| //continue; |
| throw new MetaDataException(_loc.get("embed-override-name", |
| sup, assoc.name())); |
| |
| if (scols != null && scols.length > 0) { |
| jcols = new ArrayList<>(scols.length); |
| unique = 0; |
| for (JoinColumn scol : scols) { |
| unique |= (scol.unique()) ? TRUE : FALSE; |
| jcols.add(newColumn(scol)); |
| } |
| setColumns(sup, sup.getValueInfo(), jcols, unique); |
| } else if (joinTbl != null) { |
| parseJoinTable(sup, joinTbl); |
| } |
| } |
| } |
| |
| /** |
| * Parse @AttributeOverride(s). |
| */ |
| private void parseAttributeOverrides(ClassMapping cm, |
| AttributeOverride... attrs) { |
| FieldMapping sup; |
| for (AttributeOverride attr : attrs) { |
| if (StringUtil.isEmpty(attr.name())) |
| throw new MetaDataException(_loc.get("no-override-name", cm)); |
| sup = (FieldMapping) cm.getDefinedSuperclassField(attr.name()); |
| if (sup == null) |
| sup = (FieldMapping) cm.addDefinedSuperclassField(attr.name(), |
| Object.class, Object.class); |
| if (attr.column() != null) |
| parseColumns(sup, attr.column()); |
| } |
| } |
| |
| /** |
| * Parse inheritance @PrimaryKeyJoinColumn(s). |
| */ |
| private void parsePrimaryKeyJoinColumns(ClassMapping cm, |
| PrimaryKeyJoinColumn... joins) { |
| List<Column> cols = new ArrayList<>(joins.length); |
| for (PrimaryKeyJoinColumn join : joins) |
| cols.add(newColumn(join)); |
| cm.getMappingInfo().setColumns(cols); |
| } |
| |
| /** |
| * Create a new schema column with information from the given annotation. |
| */ |
| private Column newColumn(PrimaryKeyJoinColumn join) { |
| Column col = new Column(); |
| col.setFlag(Column.FLAG_PK_JOIN, true); |
| if (!StringUtil.isEmpty(join.name())) |
| col.setIdentifier(DBIdentifier.newColumn(join.name(), delimit())); |
| if (!StringUtil.isEmpty(join.columnDefinition())) |
| col.setTypeIdentifier(DBIdentifier.newColumnDefinition(join.columnDefinition())); |
| if (!StringUtil.isEmpty(join.referencedColumnName())) |
| setTargetIdentifier(col, join.referencedColumnName()); |
| return col; |
| } |
| |
| /** |
| * Parse @SecondaryTable(s). |
| */ |
| private void parseSecondaryTables(ClassMapping cm, |
| SecondaryTable... tables) { |
| ClassMappingInfo info = cm.getMappingInfo(); |
| |
| List<Column> joins = null; |
| for (SecondaryTable table : tables) { |
| DBIdentifier sName = DBIdentifier.newTable(table.name(), delimit()); |
| if (DBIdentifier.isEmpty(sName)) |
| throw new MetaDataException(_loc.get("second-name", cm)); |
| if (!StringUtil.isEmpty(table.schema())) { |
| DBIdentifier sSchema = DBIdentifier.newSchema(table.schema(), delimit()); |
| sName = QualifiedDBIdentifier.newPath(sSchema, sName); |
| } |
| if (table.pkJoinColumns().length > 0) { |
| joins = new ArrayList<>(table.pkJoinColumns().length); |
| for (PrimaryKeyJoinColumn join : table.pkJoinColumns()) |
| joins.add(newColumn(join)); |
| info.setSecondaryTableJoinColumns(sName, joins); |
| } else { |
| info.addSecondaryTable(sName); |
| } |
| addUniqueConstraints(sName.getName(), cm, info, table.uniqueConstraints()); |
| } |
| } |
| |
| /** |
| * Set class table. |
| */ |
| private void parseTable(ClassMapping cm, Table table) { |
| if (cm.isAbstract()) |
| throw new UserException(_loc.get("table-not-allowed", cm)); |
| DBIdentifier tName = toTableIdentifier(table.schema(), table.name()); |
| if (!DBIdentifier.isNull(tName)) { |
| cm.getMappingInfo().setTableIdentifier(tName); |
| } |
| addUniqueConstraints(tName.getName(), cm, cm.getMappingInfo(), |
| table.uniqueConstraints()); |
| addIndices(tName.getName(), cm, cm.getMappingInfo(), table.indexes()); |
| } |
| |
| Unique createUniqueConstraint(MetaDataContext ctx, UniqueConstraint anno) { |
| String[] columnNames = anno.columnNames(); |
| if (columnNames == null || columnNames.length == 0) |
| throw new UserException(_loc.get("unique-no-column", ctx)); |
| DBIdentifier[] sColNames = DBIdentifier.toArray(columnNames,DBIdentifierType.COLUMN, delimit()); |
| Unique uniqueConstraint = new Unique(); |
| for (int i = 0; i < sColNames.length; i++) { |
| if (DBIdentifier.isEmpty(sColNames[i])) |
| throw new UserException(_loc.get("unique-empty-column", |
| Arrays.toString(sColNames), ctx)); |
| Column column = new Column(); |
| column.setIdentifier(sColNames[i]); |
| uniqueConstraint.addColumn(column); |
| } |
| if (!StringUtil.isEmpty(anno.name())) { |
| uniqueConstraint.setIdentifier(DBIdentifier.newConstraint(anno.name(), delimit())); |
| } |
| return uniqueConstraint; |
| } |
| |
| void addUniqueConstraints(String table, MetaDataContext ctx, |
| MappingInfo info, UniqueConstraint... uniqueConstraints) { |
| for (UniqueConstraint anno : uniqueConstraints) { |
| Unique unique = createUniqueConstraint(ctx, anno); |
| unique.setTableIdentifier(DBIdentifier.newTable(table, delimit())); |
| if (info instanceof ClassMappingInfo) |
| ((ClassMappingInfo) info).addUnique(DBIdentifier.newTable(table), unique); |
| else if (info instanceof FieldMappingInfo) |
| ((FieldMappingInfo) info).addJoinTableUnique(unique); |
| else |
| throw new InternalException(); |
| } |
| } |
| |
| |
| org.apache.openjpa.jdbc.schema.Index createIndex(MetaDataContext ctx, javax.persistence.Index anno) { |
| String columnNames = anno.columnList(); |
| if (StringUtil.isEmpty(columnNames)) |
| throw new UserException(_loc.get("index-no-column", ctx)); |
| DBIdentifier[] sColNames = DBIdentifier.toArray(columnNames.split(","), DBIdentifierType.COLUMN, delimit()); |
| org.apache.openjpa.jdbc.schema.Index indx = new org.apache.openjpa.jdbc.schema.Index(); |
| for (int i = 0; i < sColNames.length; i++) { |
| if (DBIdentifier.isEmpty(sColNames[i])) |
| throw new UserException(_loc.get("index-empty-column", |
| Arrays.toString(sColNames), ctx)); |
| Column column = new Column(); |
| column.setIdentifier(sColNames[i]); |
| indx.addColumn(column); |
| } |
| indx.setUnique(anno.unique()); |
| if (!StringUtil.isEmpty(anno.name())) { |
| indx.setIdentifier(DBIdentifier.newConstraint(anno.name(), delimit())); |
| } |
| return indx; |
| } |
| |
| void addIndices(String table, MetaDataContext ctx, |
| MappingInfo info, javax.persistence.Index... indices) { |
| for (javax.persistence.Index anno : indices) { |
| org.apache.openjpa.jdbc.schema.Index idx = createIndex(ctx, anno); |
| idx.setTableIdentifier(DBIdentifier.newTable(table, delimit())); |
| if (info instanceof ClassMappingInfo) |
| ((ClassMappingInfo) info).addIndex(DBIdentifier.newTable(table), idx); |
| else |
| throw new InternalException(); |
| } |
| } |
| |
| /** |
| * Form a qualified table name from a schema and table name. |
| */ |
| private DBIdentifier toTableIdentifier(String schema, String table) { |
| if (StringUtil.isEmpty(table)) { |
| return DBIdentifier.NULL; |
| } |
| DBIdentifier tName = DBIdentifier.newTable(table, delimit()); |
| DBIdentifier sName = DBIdentifier.newSchema(schema, delimit()); |
| if (DBIdentifier.isEmpty(tName) || DBIdentifier.isEmpty(sName)) { |
| return tName; |
| } |
| return QualifiedDBIdentifier.newPath(sName, tName); |
| } |
| |
| /** |
| * Parses the given annotation to create and cache a |
| * {@link SQLResultSetMappingMetaData}. |
| */ |
| private void parseSQLResultSetMappings(ClassMapping cm, |
| SqlResultSetMapping... annos) { |
| MappingRepository repos = (MappingRepository) getRepository(); |
| Log log = getLog(); |
| for (SqlResultSetMapping anno : annos) { |
| if (log.isTraceEnabled()) |
| log.trace(_loc.get("parse-sqlrsmapping", anno.name())); |
| |
| QueryResultMapping result = repos.getCachedQueryResultMapping |
| (null, anno.name()); |
| if (result != null) { |
| if (log.isWarnEnabled()) |
| log.warn(_loc.get("dup-sqlrsmapping", anno.name(), cm)); |
| continue; |
| } |
| |
| result = repos.addQueryResultMapping(null, anno.name()); |
| result.setSource(getSourceFile(), cm.getDescribedType(), |
| SourceTracker.SRC_ANNOTATIONS); |
| |
| for (EntityResult entity : anno.entities()) { |
| QueryResultMapping.PCResult entityResult = result.addPCResult |
| (entity.entityClass()); |
| if (!StringUtil.isEmpty(entity.discriminatorColumn())) |
| entityResult.addMapping(PCResult.DISCRIMINATOR, |
| entity.discriminatorColumn()); |
| |
| for (FieldResult field : entity.fields()) { |
| DBIdentifier sColName = DBIdentifier.newColumn(field.column(), delimit()); |
| entityResult.addMapping(field.name(), sColName.getName()); |
| } |
| } |
| for (ConstructorResult constructorResult : anno.classes()) { |
| throw new UnsupportedOperationException("JPA 2.1, not yet impl"); |
| } |
| for (ColumnResult column : anno.columns()) { |
| DBIdentifier sName = DBIdentifier.newColumn(column.name(), delimit()); |
| result.addColumnResult(sName.getName()); |
| } |
| } |
| } |
| |
| /** |
| * Parse @DiscriminatorColumn. |
| */ |
| private void parseDiscriminatorColumn(ClassMapping cm, |
| DiscriminatorColumn dcol) { |
| Column col = new Column(); |
| if (!StringUtil.isEmpty(dcol.name())) { |
| col.setIdentifier(DBIdentifier.newColumn(dcol.name(),delimit())); |
| } |
| if (!StringUtil.isEmpty(dcol.columnDefinition())) { |
| col.setTypeIdentifier(DBIdentifier.newColumnDefinition(dcol.columnDefinition())); |
| } |
| Discriminator discrim = cm.getDiscriminator(); |
| switch (dcol.discriminatorType()) { |
| case CHAR: |
| col.setJavaType(JavaTypes.CHAR); |
| discrim.setJavaType(JavaTypes.CHAR); |
| break; |
| case INTEGER: |
| col.setJavaType(JavaTypes.INT); |
| if (dcol.length() != 31) |
| col.setSize(dcol.length()); |
| discrim.setJavaType(JavaTypes.INT); |
| break; |
| default: |
| col.setJavaType(JavaTypes.STRING); |
| col.setSize(dcol.length()); |
| discrim.setJavaType(JavaTypes.STRING); |
| } |
| cm.getDiscriminator().getMappingInfo().setColumns |
| (Arrays.asList(new Column[]{ col })); |
| } |
| |
| /** |
| * Parse @Inheritance. |
| */ |
| private void parseInheritance(ClassMapping cm, Inheritance inherit) { |
| ClassMappingInfo info = cm.getMappingInfo(); |
| switch (inherit.strategy()) { |
| case SINGLE_TABLE: |
| info.setHierarchyStrategy(FlatClassStrategy.ALIAS); |
| break; |
| case JOINED: |
| info.setHierarchyStrategy(VerticalClassStrategy.ALIAS); |
| break; |
| case TABLE_PER_CLASS: |
| info.setHierarchyStrategy(FullClassStrategy.ALIAS); |
| break; |
| default: |
| throw new InternalException(); |
| } |
| } |
| |
| /** |
| * Parse class-level @MappingOverride(s). |
| */ |
| private void parseMappingOverrides(ClassMapping cm, |
| MappingOverride... overs) { |
| FieldMapping sup; |
| for (MappingOverride over : overs) { |
| if (StringUtil.isEmpty(over.name())) |
| throw new MetaDataException(_loc.get("no-override-name", cm)); |
| sup = (FieldMapping) cm.getDefinedSuperclassField(over.name()); |
| if (sup == null) |
| sup = (FieldMapping) cm.addDefinedSuperclassField(over.name(), |
| Object.class, Object.class); |
| populate(sup, over); |
| } |
| } |
| |
| /** |
| * Populate the given field from override data. |
| */ |
| private void populate(FieldMapping fm, MappingOverride over) { |
| if (over.containerTable().specified()) |
| parseContainerTable(fm, over.containerTable()); |
| parseColumns(fm, over.columns()); |
| parseXJoinColumns(fm, fm.getValueInfo(), true, over.joinColumns()); |
| parseElementJoinColumns(fm, over.elementJoinColumns()); |
| } |
| |
| /** |
| * Parse datastore identity information in @DataStoreIdColumn. |
| */ |
| private void parseDataStoreIdColumn(ClassMapping cm, DataStoreIdColumn id) { |
| Column col = new Column(); |
| if (!StringUtil.isEmpty(id.name())) |
| col.setIdentifier(DBIdentifier.newColumn(id.name(), delimit())); |
| if (!StringUtil.isEmpty(id.columnDefinition())) |
| col.setTypeIdentifier(DBIdentifier.newColumnDefinition(id.columnDefinition())); |
| if (id.precision() != 0) |
| col.setSize(id.precision()); |
| col.setFlag(Column.FLAG_UNINSERTABLE, !id.insertable()); |
| col.setFlag(Column.FLAG_UNUPDATABLE, !id.updatable()); |
| cm.getMappingInfo().setColumns(Arrays.asList(new Column[]{ col })); |
| } |
| |
| |
| /** |
| * Parse the given foreign key. |
| */ |
| private void parseForeignKey(MappingInfo info, ForeignKey fk) { |
| if (!fk.implicit()) { |
| parseForeignKey(info, fk.name(), fk.enabled(), fk.deferred(), |
| fk.deleteAction(), fk.updateAction()); |
| } else { |
| info.setImplicitRelation(true); |
| assertDefault(fk); |
| } |
| } |
| |
| /** |
| * Set foreign key data on the given mapping info. |
| */ |
| protected void parseForeignKey(MappingInfo info, String name, |
| boolean enabled, boolean deferred, ForeignKeyAction deleteAction, |
| ForeignKeyAction updateAction) { |
| if (!enabled) { |
| info.setCanForeignKey(false); |
| return; |
| } |
| |
| org.apache.openjpa.jdbc.schema.ForeignKey fk = |
| new org.apache.openjpa.jdbc.schema.ForeignKey(); |
| if (!StringUtil.isEmpty(name)) |
| fk.setIdentifier(DBIdentifier.newForeignKey(name, delimit())); |
| fk.setDeferred(deferred); |
| fk.setDeleteAction(toForeignKeyAction(deleteAction)); |
| fk.setUpdateAction(toForeignKeyAction(updateAction)); |
| info.setForeignKey(fk); |
| } |
| |
| void assertDefault(ForeignKey fk) { |
| boolean isDefault = StringUtil.isEmpty(fk.name()) |
| && fk.enabled() |
| && !fk.deferred() |
| && fk.deleteAction() == ForeignKeyAction.RESTRICT |
| && fk.updateAction() == ForeignKeyAction.RESTRICT |
| && fk.columnNames().length == 0 |
| && fk.specified(); |
| if (!isDefault) |
| throw new UserException(_loc.get("implicit-non-default-fk", _cls, |
| getSourceFile()).getMessage()); |
| } |
| |
| |
| /** |
| * Convert our FK action enum to an internal OpenJPA action. |
| */ |
| private int toForeignKeyAction(ForeignKeyAction action) { |
| switch (action) { |
| case RESTRICT: |
| return org.apache.openjpa.jdbc.schema.ForeignKey. |
| ACTION_RESTRICT; |
| case CASCADE: |
| return org.apache.openjpa.jdbc.schema.ForeignKey.ACTION_CASCADE; |
| case NULL: |
| return org.apache.openjpa.jdbc.schema.ForeignKey.ACTION_NULL; |
| case DEFAULT: |
| return org.apache.openjpa.jdbc.schema.ForeignKey.ACTION_DEFAULT; |
| default: |
| throw new InternalException(); |
| } |
| } |
| |
| /** |
| * Parse the given index. |
| */ |
| private void parseIndex(MappingInfo info, Index idx) { |
| parseIndex(info, idx.name(), idx.enabled(), idx.unique()); |
| } |
| |
| /** |
| * Set index data on the given mapping info. |
| */ |
| protected void parseIndex(MappingInfo info, String name, |
| boolean enabled, boolean unique) { |
| if (!enabled) { |
| info.setCanIndex(false); |
| return; |
| } |
| |
| org.apache.openjpa.jdbc.schema.Index idx = |
| new org.apache.openjpa.jdbc.schema.Index(); |
| if (!StringUtil.isEmpty(name)) |
| idx.setIdentifier(DBIdentifier.newConstraint(name, delimit())); |
| idx.setUnique(unique); |
| info.setIndex(idx); |
| } |
| |
| /** |
| * Set unique data on the given mapping info. |
| */ |
| private void parseUnique(FieldMapping fm, |
| org.apache.openjpa.persistence.jdbc.Unique anno) { |
| ValueMappingInfo info = fm.getValueInfo(); |
| if (!anno.enabled()) { |
| info.setCanUnique(false); |
| return; |
| } |
| |
| org.apache.openjpa.jdbc.schema.Unique unq = |
| new org.apache.openjpa.jdbc.schema.Unique(); |
| if (!StringUtil.isEmpty(anno.name())) |
| unq.setIdentifier(DBIdentifier.newIndex(anno.name(), delimit())); |
| unq.setDeferred(anno.deferred()); |
| info.setUnique(unq); |
| } |
| |
| /** |
| * Parse @VersionColumn(s). |
| */ |
| private void parseVersionColumns(ClassMapping cm, VersionColumn... vcols) { |
| if (vcols.length == 0) |
| return; |
| |
| List<Column> cols = new ArrayList<>(vcols.length); |
| for (VersionColumn vcol : vcols) |
| cols.add(newColumn(vcol, delimit())); |
| cm.getVersion().getMappingInfo().setColumns(cols); |
| } |
| |
| /** |
| * Create a new schema column with information from the given annotation. |
| */ |
| private static Column newColumn(VersionColumn anno, boolean delimit) { |
| return newColumn(anno.name(), |
| anno.nullable(), |
| anno.insertable(), |
| anno.updatable(), |
| anno.columnDefinition(), |
| anno.length(), |
| anno.precision(), |
| anno.scale(), |
| anno.table(), |
| delimit); |
| } |
| |
| static Column newColumn(String name, |
| boolean nullable, |
| boolean insertable, |
| boolean updatable, |
| String columnDefinition, |
| int length, |
| int precision, |
| int scale, |
| String table, |
| boolean delimit) { |
| Column col = new Column(); |
| col.setTableIdentifier(DBIdentifier.newTable(table, delimit)); |
| if (!StringUtil.isEmpty(name)) |
| col.setIdentifier(DBIdentifier.newColumn(name, delimit)); |
| if (precision != 0) |
| col.setSize(precision); |
| else if (length != 255) |
| col.setSize(length); |
| col.setNotNull(!nullable); |
| col.setDecimalDigits(scale); |
| if (!StringUtil.isEmpty(columnDefinition)) { |
| col.setTypeIdentifier(DBIdentifier.newColumnDefinition(columnDefinition)); |
| col.setType(Schemas.getJDBCType(col.getTypeIdentifier().getName())); |
| col.setJavaType(JavaTypes.getTypeCode(Schemas.getJavaType |
| (col.getType(), col.getSize(), col.getDecimalDigits()))); |
| } |
| col.setFlag(Column.FLAG_UNINSERTABLE, !insertable); |
| col.setFlag(Column.FLAG_UNUPDATABLE, !updatable); |
| |
| return col; |
| } |
| |
| /** |
| * Parse class-level @XMappingOverride(s). |
| */ |
| private void parseMappingOverrides(ClassMapping cm, |
| XMappingOverride... overs) { |
| FieldMapping sup; |
| for (XMappingOverride over : overs) { |
| if (StringUtil.isEmpty(over.name())) |
| throw new MetaDataException(_loc.get("no-override-name", cm)); |
| sup = (FieldMapping) cm.getDefinedSuperclassField(over.name()); |
| if (sup == null) |
| sup = (FieldMapping) cm.addDefinedSuperclassField(over.name(), |
| Object.class, Object.class); |
| populate(sup, over); |
| } |
| } |
| |
| /** |
| * Populate the given field from override data. |
| */ |
| private void populate(FieldMapping fm, XMappingOverride over) { |
| if (over.containerTable().specified()) |
| parseContainerTable(fm, over.containerTable()); |
| parseColumns(fm, over.columns()); |
| parseXJoinColumns(fm, fm.getValueInfo(), true, over.joinColumns()); |
| parseElementColumns(fm, over.elementColumns()); |
| parseElementJoinColumns(fm, over.elementJoinColumns()); |
| parseKeyColumns(fm, over.keyColumns()); |
| parseKeyJoinColumns(fm, over.keyJoinColumns()); |
| } |
| |
| /** |
| * Parse @ElementColumn(s). |
| */ |
| private void parseElementColumns(FieldMapping fm, ElementColumn... pcols) { |
| if (pcols.length == 0) |
| return; |
| |
| List<Column> cols = new ArrayList<>(pcols.length); |
| int unique = 0; |
| for (int i = 0; i < pcols.length; i++) { |
| cols.add(newColumn(pcols[i], delimit())); |
| unique |= (pcols[i].unique()) ? TRUE : FALSE; |
| } |
| setColumns(fm, fm.getElementMapping().getValueInfo(), cols, unique); |
| } |
| |
| /** |
| * Create a new schema column with information from the given annotation. |
| */ |
| private static Column newColumn(ElementColumn anno, boolean delimit) { |
| Column col = new Column(); |
| if (!StringUtil.isEmpty(anno.name())) |
| col.setIdentifier(DBIdentifier.newColumn(anno.name(), delimit)); |
| if (!StringUtil.isEmpty(anno.columnDefinition())) |
| col.setTypeIdentifier(DBIdentifier.newColumnDefinition(anno.columnDefinition())); |
| if (anno.precision() != 0) |
| col.setSize(anno.precision()); |
| else if (anno.length() != 255) |
| col.setSize(anno.length()); |
| col.setNotNull(!anno.nullable()); |
| col.setDecimalDigits(anno.scale()); |
| col.setFlag(Column.FLAG_UNINSERTABLE, !anno.insertable()); |
| col.setFlag(Column.FLAG_UNUPDATABLE, !anno.updatable()); |
| return col; |
| } |
| |
| /** |
| * Parse @KeyJoinColumn(s). |
| */ |
| private void parseKeyJoinColumns(FieldMapping fm, KeyJoinColumn... joins) { |
| if (joins.length == 0) |
| return; |
| |
| List<Column> cols = new ArrayList<>(joins.length); |
| int unique = 0; |
| for (int i = 0; i < joins.length; i++) { |
| cols.add(newColumn(joins[i], delimit())); |
| unique |= (joins[i].unique()) ? TRUE : FALSE; |
| } |
| setColumns(fm, fm.getKeyMapping().getValueInfo(), cols, unique); |
| } |
| |
| /** |
| * Create a new schema column with information from the given annotation. |
| */ |
| private static Column newColumn(KeyJoinColumn join, boolean delimit) { |
| Column col = new Column(); |
| if (!StringUtil.isEmpty(join.name())) |
| col.setIdentifier(DBIdentifier.newColumn(join.name(),delimit)); |
| if (!StringUtil.isEmpty(join.columnDefinition())) |
| col.setIdentifier(DBIdentifier.newColumnDefinition(join.columnDefinition())); |
| if (!StringUtil.isEmpty(join.referencedColumnName())) |
| col.setTargetIdentifier(DBIdentifier.newColumn(join.referencedColumnName(),delimit)); |
| if (!StringUtil.isEmpty(join.referencedAttributeName())) |
| col.setTargetField(join.referencedAttributeName()); |
| col.setNotNull(!join.nullable()); |
| col.setFlag(Column.FLAG_UNINSERTABLE, !join.insertable()); |
| col.setFlag(Column.FLAG_UNUPDATABLE, !join.updatable ()); |
| return col; |
| } |
| |
| /** |
| * Translate the fetch mode enum value to the internal OpenJPA constant. |
| */ |
| private static int toEagerFetchModeConstant(FetchMode mode) { |
| switch (mode) { |
| case NONE: |
| return EagerFetchModes.EAGER_NONE; |
| case JOIN: |
| return EagerFetchModes.EAGER_JOIN; |
| case PARALLEL: |
| return EagerFetchModes.EAGER_PARALLEL; |
| default: |
| throw new InternalException(); |
| } |
| } |
| |
| @Override |
| protected void parseLobMapping(FieldMetaData fmd) { |
| Column col = new Column(); |
| int typeCode = fmd.isElementCollection() ? fmd.getElement().getDeclaredTypeCode() : |
| fmd.getDeclaredTypeCode(); |
| Class<?> type = fmd.isElementCollection() ? fmd.getElement().getDeclaredType() : |
| fmd.getDeclaredType(); |
| |
| if (typeCode == JavaTypes.STRING |
| || type == char[].class |
| || type == Character[].class) |
| col.setType(Types.CLOB); |
| else |
| col.setType(Types.BLOB); |
| if (fmd.isElementCollection()) |
| ((FieldMapping) fmd).getElementMapping().getValueInfo().setColumns(Arrays.asList(new Column[]{ col })); |
| else |
| ((FieldMapping) fmd).getValueInfo().setColumns(Arrays.asList(new Column[]{ col })); |
| |
| } |
| |
| @Override |
| protected void parseMemberMappingAnnotations(FieldMetaData fmd) { |
| FieldMapping fm = (FieldMapping) fmd; |
| AnnotatedElement el = (AnnotatedElement) getRepository(). |
| getMetaDataFactory().getDefaults().getBackingMember(fmd); |
| |
| MappingTag tag; |
| for (Annotation anno : el.getDeclaredAnnotations()) { |
| tag = _tags.get(anno.annotationType()); |
| if (tag == null) { |
| handleUnknownMemberMappingAnnotation(fm, anno); |
| continue; |
| } |
| |
| switch (tag) { |
| case ASSOC_OVERRIDE: |
| parseAssociationOverrides(fm, (AssociationOverride) anno); |
| break; |
| case ASSOC_OVERRIDES: |
| parseAssociationOverrides(fm, ((AssociationOverrides) anno). |
| value()); |
| break; |
| case ATTR_OVERRIDE: |
| parseAttributeOverrides(fm, (AttributeOverride) anno); |
| break; |
| case ATTR_OVERRIDES: |
| parseAttributeOverrides(fm, ((AttributeOverrides) anno). |
| value()); |
| break; |
| case COL: |
| parseColumns(fm, (javax.persistence.Column) anno); |
| break; |
| case COLS: |
| parseColumns(fm, ((Columns) anno).value()); |
| break; |
| case ENUMERATED: |
| parseEnumerated(fm, (Enumerated) anno); |
| break; |
| case JOIN_COL: |
| parseJoinColumns(fm, fm.getValueInfo(), true, (JoinColumn) anno); |
| break; |
| case JOIN_COLS: |
| parseJoinColumns(fm, fm.getValueInfo(), true, ((JoinColumns) anno).value()); |
| break; |
| case JOIN_TABLE: |
| parseJoinTable(fm, (JoinTable) anno); |
| break; |
| case KEY_CLASS_CRIT: |
| fm.getKeyMapping().getValueInfo().setUseClassCriteria |
| (((KeyClassCriteria) anno).value()); |
| break; |
| case KEY_COL: |
| parseKeyColumns(fm, (KeyColumn) anno); |
| break; |
| case KEY_COLS: |
| parseKeyColumns(fm, ((KeyColumns) anno).value()); |
| break; |
| case KEY_EMBEDDED_MAPPING: |
| KeyEmbeddedMapping kembed = (KeyEmbeddedMapping) anno; |
| parseEmbeddedMapping(fm.getKeyMapping(), |
| DBIdentifier.newColumn(kembed.nullIndicatorColumnName(), delimit()), |
| DBIdentifier.newConstant(kembed.nullIndicatorAttributeName()), |
| kembed.overrides()); |
| break; |
| case KEY_FK: |
| KeyForeignKey kfk = (KeyForeignKey) anno; |
| parseForeignKey(fm.getKeyMapping().getValueInfo(), |
| kfk.name(), kfk.enabled(), kfk.deferred(), |
| kfk.deleteAction(), kfk.updateAction()); |
| break; |
| case KEY_INDEX: |
| KeyIndex kidx = (KeyIndex) anno; |
| parseIndex(fm.getKeyMapping().getValueInfo(), kidx.name(), |
| kidx.enabled(), kidx.unique()); |
| break; |
| case KEY_JOIN_COL: |
| parseKeyJoinColumns(fm, (KeyJoinColumn) anno); |
| break; |
| case KEY_JOIN_COLS: |
| parseKeyJoinColumns(fm, ((KeyJoinColumns) anno).value()); |
| break; |
| case KEY_NONPOLY: |
| fm.getKeyMapping().setPolymorphic(toPolymorphicConstant |
| (((KeyNonpolymorphic) anno).value())); |
| break; |
| case KEY_STRAT: |
| fm.getKeyMapping().getValueInfo() |
| .setStrategy(((KeyStrategy) anno).value()); |
| break; |
| case MAP_KEY_COL: |
| parseMapKeyColumn(fm, (MapKeyColumn) anno); |
| break; |
| case MAP_KEY_ENUMERATED: |
| parseMapKeyEnumerated(fm, (MapKeyEnumerated) anno); |
| break; |
| case MAP_KEY_JOIN_COL: |
| parseMapKeyJoinColumns(fm, (MapKeyJoinColumn) anno); |
| break; |
| case MAP_KEY_JOIN_COLS: |
| parseMapKeyJoinColumns(fm, |
| ((MapKeyJoinColumns) anno).value()); |
| break; |
| case PK_JOIN_COL: |
| parsePrimaryKeyJoinColumns(fm, (PrimaryKeyJoinColumn) anno); |
| break; |
| case PK_JOIN_COLS: |
| parsePrimaryKeyJoinColumns(fm, |
| ((PrimaryKeyJoinColumns) anno). |
| value()); |
| break; |
| case TABLE_GEN: |
| parseTableGenerator(el, (TableGenerator) anno); |
| break; |
| case TEMPORAL: |
| parseTemporal(fm, (Temporal) anno); |
| break; |
| case MAP_KEY_TEMPORAL: |
| parseMapKeyTemporal(fm, (MapKeyTemporal) anno); |
| break; |
| case CLASS_CRIT: |
| fm.getValueInfo().setUseClassCriteria |
| (((ClassCriteria) anno).value()); |
| break; |
| case CONTAINER_TABLE: |
| parseContainerTable(fm, (ContainerTable) anno); |
| break; |
| case COLLECTION_TABLE: |
| parseCollectionTable(fm, (CollectionTable) anno); |
| break; |
| case EAGER_FETCH_MODE: |
| fm.setEagerFetchMode(toEagerFetchModeConstant |
| (((EagerFetchMode) anno).value())); |
| break; |
| case ELEM_CLASS_CRIT: |
| fm.getElementMapping().getValueInfo().setUseClassCriteria |
| (((ElementClassCriteria) anno).value()); |
| break; |
| case ELEM_COL: |
| parseElementColumns(fm, (ElementColumn) anno); |
| break; |
| case ELEM_COLS: |
| parseElementColumns(fm, ((ElementColumns) anno).value()); |
| break; |
| case ELEM_EMBEDDED_MAPPING: |
| ElementEmbeddedMapping ee = (ElementEmbeddedMapping) anno; |
| parseEmbeddedMapping(fm.getElementMapping(), |
| DBIdentifier.newConstant(ee.nullIndicatorAttributeName()), |
| DBIdentifier.newColumn(ee.nullIndicatorColumnName(), delimit()), |
| ee.overrides()); |
| break; |
| case ELEM_FK: |
| ElementForeignKey efk = (ElementForeignKey) anno; |
| parseForeignKey(fm.getElementMapping().getValueInfo(), |
| efk.name(), efk.enabled(), efk.deferred(), |
| efk.deleteAction(), efk.updateAction()); |
| break; |
| case ELEM_INDEX: |
| ElementIndex eidx = (ElementIndex) anno; |
| parseIndex(fm.getElementMapping().getValueInfo(), |
| eidx.name(), eidx.enabled(), eidx.unique()); |
| break; |
| case ELEM_JOIN_COL: |
| parseElementJoinColumns(fm, (ElementJoinColumn) anno); |
| break; |
| case ELEM_JOIN_COLS: |
| parseElementJoinColumns(fm, ((ElementJoinColumns) anno). |
| value()); |
| break; |
| case ELEM_NONPOLY: |
| fm.getElementMapping().setPolymorphic(toPolymorphicConstant |
| (((ElementNonpolymorphic) anno).value())); |
| break; |
| case ELEM_STRAT: |
| fm.getElementMapping().getValueInfo() |
| .setStrategy(((ElementStrategy) anno).value()); |
| break; |
| case EMBEDDED_MAPPING: |
| parseEmbeddedMapping(fm, (EmbeddedMapping) anno); |
| break; |
| case FK: |
| parseForeignKey(fm.getValueInfo(), (ForeignKey) anno); |
| break; |
| case INDEX: |
| parseIndex(fm.getValueInfo(), (Index) anno); |
| break; |
| case NONPOLY: |
| fm.setPolymorphic(toPolymorphicConstant |
| (((Nonpolymorphic) anno).value())); |
| break; |
| case ORDER_COLUMN: |
| parseJavaxOrderColumn(fm, |
| (javax.persistence.OrderColumn)anno); |
| break; |
| case ORDER_COL: |
| parseOrderColumn(fm, (OrderColumn) anno); |
| break; |
| case STRAT: |
| fm.getMappingInfo().setStrategy(((Strategy) anno).value()); |
| break; |
| case UNIQUE: |
| parseUnique(fm, |
| (org.apache.openjpa.persistence.jdbc.Unique) anno); |
| break; |
| case X_EMBEDDED_MAPPING: |
| XEmbeddedMapping embed = (XEmbeddedMapping) anno; |
| parseEmbeddedMapping(fm, DBIdentifier.newColumn(embed.nullIndicatorColumnName(), delimit()), |
| DBIdentifier.newConstant(embed.nullIndicatorAttributeName()), embed.overrides()); |
| break; |
| case X_JOIN_COL: |
| parseXJoinColumns(fm, fm.getValueInfo(), true, |
| (XJoinColumn) anno); |
| break; |
| case X_JOIN_COLS: |
| parseXJoinColumns(fm, fm.getValueInfo(), true, |
| ((XJoinColumns) anno).value()); |
| break; |
| default: |
| throw new UnsupportedException(_loc.get("unsupported", fm, |
| anno.toString())); |
| } |
| } |
| } |
| |
| /** |
| * Allow subclasses to handle unknown annotations. |
| */ |
| protected boolean handleUnknownMemberMappingAnnotation(FieldMapping fm, |
| Annotation anno) { |
| return false; |
| } |
| |
| /** |
| * Return the {@link ValueMapping} <code>POLY_*</code> constant for |
| * the given enum value. |
| */ |
| protected static int toPolymorphicConstant(NonpolymorphicType val) { |
| switch (val) { |
| case EXACT: |
| return ValueMapping.POLY_FALSE; |
| case JOINABLE: |
| return ValueMapping.POLY_JOINABLE; |
| case FALSE: |
| return ValueMapping.POLY_TRUE; |
| default: |
| throw new InternalException(); |
| } |
| } |
| |
| /** |
| * Parse given @AssociationOverride annotations on an embedded mapping. |
| */ |
| private void parseAssociationOverrides(FieldMapping fm, |
| AssociationOverride... assocs) { |
| |
| FieldMapping efm; |
| JoinColumn[] ecols; |
| int unique; |
| List<Column> jcols; |
| JoinTable joinTbl; |
| for (AssociationOverride assoc : assocs) { |
| efm = getEmbeddedFieldMapping(fm, assoc.name()); |
| if (efm == null) |
| throw new MetaDataException(_loc.get("embed-override-name", |
| fm, assoc.name())); |
| ecols = assoc.joinColumns(); |
| joinTbl = assoc.joinTable(); |
| if ((ecols == null || ecols.length == 0) && joinTbl == null) |
| throw new MetaDataException(_loc.get("embed-override-name", |
| fm, assoc.name())); |
| if (ecols != null && ecols.length > 0) { |
| unique = 0; |
| jcols = new ArrayList<>(ecols.length); |
| for (JoinColumn ecol : ecols) { |
| unique |= (ecol.unique()) ? TRUE : FALSE; |
| jcols.add(newColumn(ecol)); |
| } |
| setColumns(efm, efm.getValueInfo(), jcols, unique); |
| } else if (joinTbl != null) { |
| parseJoinTable(efm, joinTbl); |
| } |
| } |
| } |
| |
| /** |
| * Parse given @AttributeOverride annotations on an embedded mapping. |
| */ |
| private void parseAttributeOverrides(FieldMapping fm, |
| AttributeOverride... attrs) { |
| for (AttributeOverride attr : attrs) { |
| String attrName = attr.name(); |
| FieldMapping efm = getEmbeddedFieldMapping(fm, attrName); |
| if (attr.column() != null) |
| parseColumns(efm, attr.column()); |
| } |
| } |
| |
| public static FieldMapping getEmbeddedFieldMapping(FieldMapping fm, |
| String attrName) { |
| return getEmbeddedFieldMapping(fm, attrName, true); |
| } |
| |
| public static FieldMapping getEmbeddedFieldMapping(FieldMapping fm, |
| String attrName, boolean mustExist) { |
| ClassMapping embed = null; |
| boolean isKey = false; |
| boolean isValue = false; |
| if (attrName != null && attrName.startsWith("key.")) |
| isKey = true; |
| else if (attrName != null && attrName.startsWith("value.")) |
| isValue = true; |
| if (isKey || isValue) |
| attrName = attrName.substring(attrName.indexOf(".")+1); |
| |
| int typeCode = fm.getValue().getDeclaredTypeCode(); |
| switch (typeCode) { |
| case JavaTypes.COLLECTION : // a collection of embeddables |
| if (isKey || isValue) |
| throw new MetaDataException(_loc.get("embed-override-name", |
| fm, attrName)); |
| embed = fm.getElementMapping().getEmbeddedMapping(); |
| break; |
| case JavaTypes.MAP: // a map |
| if (!isKey && !isValue) |
| throw new MetaDataException(_loc.get("embed-override-name", |
| fm, attrName)); |
| if (isKey) |
| embed = getEmbeddedMapping(fm.getKeyMapping(), mustExist); |
| else if (isValue) |
| embed = getEmbeddedMapping(fm.getElementMapping(), |
| mustExist); |
| break; |
| default: // an embeddable |
| if (isKey || isValue) |
| throw new MetaDataException(_loc.get("embed-override-name", |
| fm, attrName)); |
| embed = getEmbeddedMapping(fm.getValueMapping(), mustExist); |
| break; |
| } |
| |
| if (embed == null) { |
| if (mustExist) |
| throw new MetaDataException(_loc.get("not-embedded", fm)); |
| return null; |
| } |
| return getAttributeOverrideField(attrName, fm, embed); |
| } |
| |
| public static Class<?> getEmbeddedClassType(FieldMapping fm, |
| String attrName) { |
| ValueMapping embed = null; |
| boolean isKey = false; |
| boolean isValue = false; |
| if (attrName != null && attrName.startsWith("key.")) |
| isKey = true; |
| else if (attrName != null && attrName.startsWith("value.")) |
| isValue = true; |
| if (isKey || isValue) |
| attrName = attrName.substring(attrName.indexOf(".")+1); |
| |
| int typeCode = fm.getValue().getDeclaredTypeCode(); |
| switch (typeCode) { |
| case JavaTypes.COLLECTION : // a collection of embeddables |
| if (isKey || isValue) |
| throw new MetaDataException(_loc.get("embed-override-name", |
| fm, attrName)); |
| embed = fm.getElementMapping(); |
| break; |
| case JavaTypes.MAP: // a map |
| if (!isKey && !isValue) |
| throw new MetaDataException(_loc.get("embed-override-name", |
| fm, attrName)); |
| if (isKey) |
| embed = fm.getKeyMapping(); |
| else if (isValue) |
| embed = fm.getElementMapping(); |
| break; |
| default: // an embeddable |
| if (isKey || isValue) |
| throw new MetaDataException(_loc.get("embed-override-name", |
| fm, attrName)); |
| embed = fm.getValueMapping(); |
| break; |
| } |
| |
| if (embed == null) { |
| throw new MetaDataException(_loc.get("not-embedded", fm)); |
| } |
| return embed.getDeclaredType(); |
| } |
| |
| public static ClassMapping getEmbeddedMapping(ValueMapping val, boolean |
| createNew) { |
| ClassMapping embed = val.getEmbeddedMapping(); |
| if (embed != null || !createNew) |
| return embed; |
| |
| val.addEmbeddedMetaData(); |
| return val.getEmbeddedMapping(); |
| } |
| |
| |
| public static ClassMapping getEmbeddedMapping(ValueMapping val) { |
| return getEmbeddedMapping(val, true); |
| } |
| |
| public static FieldMapping getAttributeOverrideField(String attrName, |
| FieldMapping fm, ClassMapping embed) { |
| FieldMapping efm; |
| int idxOfDot = attrName.indexOf("."); |
| if (idxOfDot == -1) { |
| efm = embed.getFieldMapping(attrName); |
| if (efm == null) |
| throw new MetaDataException(_loc.get("embed-override-name", |
| fm, attrName)); |
| return efm; |
| } |
| String attrName1 = attrName.substring(0, idxOfDot); |
| String attrName2 = attrName.substring(idxOfDot+1); |
| efm = embed.getFieldMapping(attrName1); |
| if (efm == null) |
| throw new MetaDataException(_loc.get("embed-override-name", |
| fm, attrName1)); |
| ClassMapping embed1 = getEmbeddedMapping(efm.getValueMapping()); |
| return getAttributeOverrideField(attrName2, efm, embed1); |
| } |
| |
| /** |
| * Parse @Enumerated. |
| */ |
| private void parseEnumerated(FieldMapping fm, Enumerated anno) { |
| String strat = EnumValueHandler.class.getName() + "(StoreOrdinal=" |
| + String.valueOf(anno.value() == EnumType.ORDINAL) + ")"; |
| if (fm.isElementCollection()) |
| fm.getElementMapping().getValueInfo().setStrategy(strat); |
| else |
| fm.getValueInfo().setStrategy(strat); |
| } |
| |
| /** |
| * Parse @MapKeyEnumerated. |
| */ |
| private void parseMapKeyEnumerated(FieldMapping fm, MapKeyEnumerated anno) { |
| String strat = EnumValueHandler.class.getName() + "(StoreOrdinal=" |
| + String.valueOf(anno.value() == EnumType.ORDINAL) + ")"; |
| fm.getKeyMapping().getValueInfo().setStrategy(strat); |
| } |
| |
| /** |
| * Parse @Temporal. |
| */ |
| private void parseTemporal(FieldMapping fm, Temporal anno) { |
| List<Column> cols = fm.getValueInfo().getColumns(); |
| if (!cols.isEmpty() && cols.size() != 1) |
| throw new MetaDataException(_loc.get("num-cols-mismatch", fm, |
| String.valueOf(cols.size()), "1")); |
| if (cols.isEmpty()) { |
| cols = Arrays.asList(new Column[]{ new Column() }); |
| if (fm.isElementCollection()) { |
| if (!fm.getElementMapping().getValueInfo().getColumns().isEmpty()) |
| cols = fm.getElementMapping().getValueInfo().getColumns(); |
| else |
| fm.getElementMapping().getValueInfo().setColumns(cols); |
| } else |
| fm.getValueInfo().setColumns(cols); |
| } |
| |
| Column col = (Column) cols.get(0); |
| switch (anno.value()) { |
| case DATE: |
| col.setType(Types.DATE); |
| break; |
| case TIME: |
| col.setType(Types.TIME); |
| break; |
| case TIMESTAMP: |
| col.setType(Types.TIMESTAMP); |
| break; |
| } |
| } |
| |
| /** |
| * Parse @Temporal. |
| */ |
| private void parseMapKeyTemporal(FieldMapping fm, MapKeyTemporal anno) { |
| List<Column> cols = fm.getKeyMapping().getValueInfo().getColumns(); |
| if (!cols.isEmpty() && cols.size() != 1) |
| throw new MetaDataException(_loc.get("num-cols-mismatch", fm, |
| String.valueOf(cols.size()), "1")); |
| if (cols.isEmpty()) { |
| cols = Arrays.asList(new Column[]{ new Column() }); |
| fm.getKeyMapping().getValueInfo().setColumns(cols); |
| } |
| |
| Column col = (Column) cols.get(0); |
| switch (anno.value()) { |
| case DATE: |
| col.setType(Types.DATE); |
| break; |
| case TIME: |
| col.setType(Types.TIME); |
| break; |
| case TIMESTAMP: |
| col.setType(Types.TIMESTAMP); |
| break; |
| } |
| } |
| |
| /** |
| * Parse @Column(s). |
| */ |
| protected void parseColumns(FieldMapping fm, |
| javax.persistence.Column... pcols) { |
| if (pcols.length == 0) |
| return; |
| |
| // might already have some column information from mapping annotation |
| List<Column> cols = fm.getValueInfo().getColumns(); |
| if (!cols.isEmpty() && cols.size() != pcols.length) |
| throw new MetaDataException(_loc.get("num-cols-mismatch", fm, |
| String.valueOf(cols.size()), String.valueOf(pcols.length))); |
| |
| // cache the JAXB XmlRootElement class if it is present so we do not |
| // have a hard-wired dependency on JAXB here |
| Class<?> xmlRootElementClass = null; |
| try { |
| xmlRootElementClass = Class.forName("javax.xml.bind.annotation.XmlRootElement"); |
| } catch (Exception e) { |
| } |
| |
| int unique = 0; |
| DBIdentifier sSecondary = DBIdentifier.NULL; |
| for (int i = 0; i < pcols.length; i++) { |
| if (cols.size() > i) |
| setupColumn((Column) cols.get(i), pcols[i], delimit()); |
| else { |
| if (cols.isEmpty()) |
| cols = new ArrayList<>(pcols.length); |
| cols.add(newColumn(pcols[i], delimit())); |
| } |
| if (xmlRootElementClass != null |
| && StringUtil.isEmpty(pcols[i].columnDefinition()) |
| && (AccessController.doPrivileged(J2DoPrivHelper |
| .isAnnotationPresentAction(fm.getDeclaredType(), |
| (Class<? extends Annotation>) xmlRootElementClass))).booleanValue()) { |
| DBDictionary dict = ((MappingRepository) getRepository()) |
| .getDBDictionary(); |
| if (dict.supportsXMLColumn) |
| // column maps to xml type |
| cols.get(i).setTypeIdentifier(DBIdentifier.newColumnDefinition(dict.xmlTypeName)); |
| } |
| |
| unique |= (pcols[i].unique()) ? TRUE : FALSE; |
| DBIdentifier sSecTable = DBIdentifier.newTable(pcols[i].table(), delimit()); |
| sSecondary = trackSecondaryTable(fm, sSecondary, sSecTable, i); |
| } |
| |
| if (fm.isElementCollection()) |
| setColumns(fm, fm.getElementMapping().getValueInfo(), cols, unique); |
| else |
| setColumns(fm, fm.getValueInfo(), cols, unique); |
| if (!DBIdentifier.isNull(sSecondary)) |
| fm.getMappingInfo().setTableIdentifier(sSecondary); |
| } |
| |
| /** |
| * Create a new schema column with information from the given annotation. |
| */ |
| private static Column newColumn(javax.persistence.Column anno, |
| boolean delimit) { |
| Column col = new Column(); |
| setupColumn(col, anno, delimit); |
| return col; |
| } |
| |
| /** |
| * Setup the given column with information from the given annotation. |
| */ |
| private static void setupColumn(Column col, javax.persistence.Column anno, |
| boolean delimit) { |
| if (!StringUtil.isEmpty(anno.name())) |
| col.setIdentifier(DBIdentifier.newColumn(anno.name(),delimit)); |
| if (!StringUtil.isEmpty(anno.columnDefinition())) |
| col.setTypeIdentifier(DBIdentifier.newColumnDefinition(anno.columnDefinition())); |
| if (anno.precision() != 0) |
| col.setSize(anno.precision()); |
| else if (anno.length() != 255) |
| col.setSize(anno.length()); |
| col.setNotNull(!anno.nullable()); |
| col.setDecimalDigits(anno.scale()); |
| col.setFlag(Column.FLAG_UNINSERTABLE, !anno.insertable()); |
| col.setFlag(Column.FLAG_UNUPDATABLE, !anno.updatable()); |
| } |
| |
| /** |
| * Set the given columns as the columns for <code>fm</code>. |
| * |
| * @param unique bitwise combination of TRUE and FALSE for the |
| * unique attribute of each column |
| */ |
| protected void setColumns(FieldMapping fm, MappingInfo info, |
| List<Column> cols, int unique) { |
| info.setColumns(cols); |
| if (unique == TRUE) |
| info.setUnique(new org.apache.openjpa.jdbc.schema.Unique()); |
| |
| //### EJB3 |
| Log log = getLog(); |
| if (log.isWarnEnabled() && unique == (TRUE | FALSE)) |
| log.warn(_loc.get("inconsist-col-attrs", fm)); |
| } |
| |
| /** |
| * Helper to track the secondary table for a set of columns. |
| * |
| * @param secondary secondary table for last column |
| * @param colSecondary secondary table for current column |
| * @return secondary table for field |
| */ |
| private DBIdentifier trackSecondaryTable(FieldMapping fm, DBIdentifier secondary, |
| DBIdentifier colSecondary, int col) { |
| if (DBIdentifier.isEmpty(colSecondary)) |
| colSecondary = DBIdentifier.NULL; |
| if (col == 0) |
| return colSecondary; |
| if (!DBIdentifier.equalsIgnoreCase(secondary, colSecondary)) |
| throw new MetaDataException(_loc.get("second-inconsist", fm)); |
| return secondary; |
| } |
| |
| /** |
| * Parse @JoinTable. |
| */ |
| private void parseJoinTable(FieldMapping fm, JoinTable join) { |
| FieldMappingInfo info = fm.getMappingInfo(); |
| DBIdentifier joinTbl = toTableIdentifier(join.schema(), join.name()); |
| info.setTableIdentifier(joinTbl); |
| parseJoinColumns(fm, info, false, join.joinColumns()); |
| parseJoinColumns(fm, fm.getElementMapping().getValueInfo(), false, |
| join.inverseJoinColumns()); |
| addUniqueConstraints(info.getTableIdentifier().getName(), fm, info, |
| join.uniqueConstraints()); |
| } |
| |
| /** |
| * Parse given @JoinColumn annotations. |
| */ |
| private void parseJoinColumns(FieldMapping fm, MappingInfo info, |
| boolean secondaryAllowed, JoinColumn... joins) { |
| if (joins.length == 0) |
| return; |
| |
| List<Column> cols = new ArrayList<>(joins.length); |
| int unique = 0; |
| DBIdentifier sSecondary = DBIdentifier.NULL; |
| |
| for (int i = 0; i < joins.length; i++) { |
| Column col = newColumn(joins[i]); |
| cols.add(col); |
| unique |= (joins[i].unique()) ? TRUE : FALSE; |
| DBIdentifier sTable = DBIdentifier.NULL; |
| if (info instanceof FieldMappingInfo && secondaryAllowed) { |
| sTable = ((FieldMappingInfo)info).getTableIdentifier(); |
| } |
| if (sTable.isNull()) { |
| sTable = DBIdentifier.newTable(joins[i].table(), delimit()); |
| } |
| sSecondary = trackSecondaryTable(fm, sSecondary, sTable, i); |
| if (!secondaryAllowed && !DBIdentifier.isNull(sSecondary)) |
| throw new MetaDataException(_loc.get("bad-second", fm)); |
| } |
| |
| setColumns(fm, info, cols, unique); |
| if (!DBIdentifier.isNull(sSecondary)) |
| fm.getMappingInfo().setTableIdentifier(sSecondary); |
| String mappedByIdValue = fm.getMappedByIdValue(); |
| if (mappedByIdValue != null) { |
| FieldMapping[] pks = fm.getDefiningMapping().getPrimaryKeyFieldMappings(); |
| pks[0].setMapsIdCols(true); |
| if (mappedByIdValue.length() == 0) { |
| pks[0].getValueInfo().setMapsIdColumns(cols); |
| } else { |
| ClassMapping embeddedMeta = (ClassMapping)pks[0].getValue().getEmbeddedMetaData(); |
| if (embeddedMeta != null) { |
| FieldMapping fmd = embeddedMeta.getFieldMapping(mappedByIdValue); |
| if (fmd != null) |
| fmd.getValueInfo().setMapsIdColumns(cols); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Create a new schema column with information from the given annotation. |
| */ |
| private Column newColumn(JoinColumn join) { |
| Column col = new Column(); |
| if (!StringUtil.isEmpty(join.name())) |
| col.setIdentifier(DBIdentifier.newColumn(join.name(), delimit())); |
| if (!StringUtil.isEmpty(join.columnDefinition())) |
| col.setTypeIdentifier(DBIdentifier.newColumnDefinition(join.columnDefinition())); |
| String refColumnName = join.referencedColumnName(); |
| if (!StringUtil.isEmpty(refColumnName)) { |
| setTargetIdentifier(col, refColumnName); |
| } |
| col.setNotNull(!join.nullable()); |
| col.setFlag(Column.FLAG_UNINSERTABLE, !join.insertable()); |
| col.setFlag(Column.FLAG_UNUPDATABLE, !join.updatable()); |
| return col; |
| } |
| |
| /** |
| * Sets reference column name of the given column taking into account |
| * that the given reference name that begins with a single quote represents |
| * special meaning of a constant join column and hence not to be delimited. |
| * @param col |
| * @param refColumnName |
| * @see <a href="http://issues.apache.org/jira/browse/OPENJPA-1979">OPENJPA-1979</a> |
| */ |
| private static final char SINGLE_QUOTE = '\''; |
| protected void setTargetIdentifier(Column col, String refColumnName) { |
| if (refColumnName.charAt(0) == SINGLE_QUOTE) { |
| col.setTargetIdentifier(DBIdentifier.newConstant(refColumnName)); |
| } else { |
| col.setTargetIdentifier(DBIdentifier.newColumn(refColumnName, delimit())); |
| } |
| } |
| |
| /** |
| * Parse @KeyColumn(s). |
| */ |
| private void parseKeyColumns(FieldMapping fm, KeyColumn... pcols) { |
| if (pcols.length == 0) |
| return; |
| |
| List<Column> cols = new ArrayList<>(pcols.length); |
| int unique = 0; |
| for (int i = 0; i < pcols.length; i++) { |
| cols.add(newColumn(pcols[i], delimit())); |
| unique |= (pcols[i].unique()) ? TRUE : FALSE; |
| } |
| setColumns(fm, fm.getKeyMapping().getValueInfo(), cols, unique); |
| } |
| |
| /** |
| * Create a new schema column with information from the given annotation. |
| */ |
| private static Column newColumn(KeyColumn anno, boolean delimit) { |
| Column col = new Column(); |
| if (!StringUtil.isEmpty(anno.name())) |
| col.setIdentifier(DBIdentifier.newColumn(anno.name(), delimit)); |
| if (!StringUtil.isEmpty(anno.columnDefinition())) |
| col.setTypeIdentifier(DBIdentifier.newColumnDefinition(anno.columnDefinition())); |
| if (anno.precision() != 0) |
| col.setSize(anno.precision()); |
| else if (anno.length() != 255) |
| col.setSize(anno.length()); |
| col.setNotNull(!anno.nullable()); |
| col.setDecimalDigits(anno.scale()); |
| col.setFlag(Column.FLAG_UNINSERTABLE, !anno.insertable()); |
| col.setFlag(Column.FLAG_UNUPDATABLE, !anno.updatable()); |
| return col; |
| } |
| |
| /** |
| * Parse given @PrimaryKeyJoinColumn annotations. |
| */ |
| private void parsePrimaryKeyJoinColumns(FieldMapping fm, |
| PrimaryKeyJoinColumn... joins) { |
| List<Column> cols = new ArrayList<>(joins.length); |
| for (PrimaryKeyJoinColumn join : joins) |
| cols.add(newColumn(join)); |
| setColumns(fm, fm.getValueInfo(), cols, 0); |
| } |
| |
| /** |
| * Parse given @XJoinColumn annotations. |
| */ |
| protected void parseXJoinColumns(FieldMapping fm, MappingInfo info, |
| boolean secondaryAllowed, XJoinColumn... joins) { |
| if (joins.length == 0) |
| return; |
| |
| List<Column> cols = new ArrayList<>(joins.length); |
| int unique = 0; |
| DBIdentifier sSecondary = DBIdentifier.NULL; |
| for (int i = 0; i < joins.length; i++) { |
| cols.add(newColumn(joins[i], delimit())); |
| unique |= (joins[i].unique()) ? TRUE : FALSE; |
| sSecondary = trackSecondaryTable(fm, sSecondary, |
| DBIdentifier.newTable(joins[i].table(), delimit()), i); |
| if (!secondaryAllowed && !DBIdentifier.isNull(sSecondary)) |
| throw new MetaDataException(_loc.get("bad-second", fm)); |
| } |
| |
| setColumns(fm, info, cols, unique); |
| if (!DBIdentifier.isNull(sSecondary)) |
| fm.getMappingInfo().setTableIdentifier(sSecondary); |
| } |
| |
| /** |
| * Create a new schema column with information from the given annotation. |
| */ |
| private Column newColumn(XJoinColumn join, boolean delimit) { |
| Column col = new Column(); |
| if (!StringUtil.isEmpty(join.name())) |
| col.setIdentifier(DBIdentifier.newColumn(join.name(), delimit)); |
| if (!StringUtil.isEmpty(join.columnDefinition())) |
| col.setTypeIdentifier(DBIdentifier.newColumnDefinition(join.columnDefinition())); |
| if (!StringUtil.isEmpty(join.referencedColumnName())) |
| setTargetIdentifier(col, join.referencedColumnName()); |
| if (!StringUtil.isEmpty(join.referencedAttributeName())) |
| col.setTargetField(join.referencedAttributeName()); |
| col.setNotNull(!join.nullable()); |
| col.setFlag(Column.FLAG_UNINSERTABLE, !join.insertable()); |
| col.setFlag(Column.FLAG_UNUPDATABLE, !join.updatable()); |
| return col; |
| } |
| |
| /** |
| * Parse embedded info for the given mapping. |
| */ |
| private void parseEmbeddedMapping(FieldMapping fm, EmbeddedMapping anno) { |
| ClassMapping embed = fm.getEmbeddedMapping(); |
| if (embed == null) |
| throw new MetaDataException(_loc.get("not-embedded", fm)); |
| |
| FieldMapping efm; |
| for (MappingOverride over : anno.overrides()) { |
| efm = embed.getFieldMapping(over.name()); |
| if (efm == null) |
| throw new MetaDataException(_loc.get("embed-override-name", |
| fm, over.name())); |
| populate(efm, over); |
| } |
| |
| DBIdentifier nullInd = DBIdentifier.NULL; |
| if (!StringUtil.isEmpty(anno.nullIndicatorAttributeName())) |
| nullInd = DBIdentifier.newConstant(anno.nullIndicatorAttributeName()); |
| else if (!StringUtil.isEmpty(anno.nullIndicatorColumnName())) |
| nullInd = DBIdentifier.newColumn(anno.nullIndicatorColumnName(), delimit()); |
| if (DBIdentifier.isNull(nullInd)) |
| return; |
| |
| ValueMappingInfo info = fm.getValueInfo(); |
| populateNullIndicator(nullInd, info); |
| } |
| |
| /** |
| * Parse embedded info for the given mapping. |
| */ |
| private void parseEmbeddedMapping(ValueMapping vm, |
| DBIdentifier nullIndicatorAttribute, DBIdentifier nullIndicatorColumn, |
| XMappingOverride[] overrides) { |
| ClassMapping embed = vm.getEmbeddedMapping(); |
| if (embed == null) |
| throw new MetaDataException(_loc.get("not-embedded", vm)); |
| |
| FieldMapping efm; |
| for (XMappingOverride over : overrides) { |
| efm = embed.getFieldMapping(over.name()); |
| if (efm == null) |
| throw new MetaDataException(_loc.get("embed-override-name", |
| vm, over.name())); |
| populate(efm, over); |
| } |
| |
| DBIdentifier nullInd = DBIdentifier.NULL; |
| if (!DBIdentifier.isEmpty(nullIndicatorAttribute)) |
| nullInd = nullIndicatorAttribute; |
| else if (!DBIdentifier.isEmpty(nullIndicatorColumn)) |
| nullInd = nullIndicatorColumn; |
| if (DBIdentifier.isNull(nullInd)) |
| return; |
| |
| ValueMappingInfo info = vm.getValueInfo(); |
| populateNullIndicator(nullInd, info); |
| } |
| |
| private void populateNullIndicator(DBIdentifier nullInd, ValueMappingInfo info) { |
| if ("false".equals(nullInd.getName())) |
| info.setCanIndicateNull(false); |
| else { |
| Column col = new Column(); |
| if (!"true".equals(nullInd.getName())) |
| col.setIdentifier(nullInd); |
| info.setColumns(Arrays.asList(new Column[]{ col })); |
| } |
| } |
| |
| /** |
| * Parse @ContainerTable. |
| */ |
| protected void parseContainerTable(FieldMapping fm, ContainerTable ctbl) { |
| DBIdentifier tblName = toTableIdentifier(ctbl.schema(), ctbl.name()); |
| fm.getMappingInfo().setTableIdentifier(tblName); |
| parseXJoinColumns(fm, fm.getMappingInfo(), false, ctbl.joinColumns()); |
| if (ctbl.joinForeignKey().specified()) |
| parseForeignKey(fm.getMappingInfo(), ctbl.joinForeignKey()); |
| if (ctbl.joinIndex().specified()) |
| parseIndex(fm.getMappingInfo(), ctbl.joinIndex()); |
| } |
| |
| /** |
| * Parse @CollectionTable. |
| */ |
| protected void parseCollectionTable(FieldMapping fm, CollectionTable ctbl) { |
| FieldMappingInfo info = fm.getMappingInfo(); |
| DBIdentifier tblName = toTableIdentifier(ctbl.schema(), ctbl.name()); |
| info.setTableIdentifier(tblName); |
| //ctbl.catalog() |
| parseJoinColumns(fm, fm.getMappingInfo(), false, ctbl.joinColumns()); |
| addUniqueConstraints(info.getTableIdentifier().getName(), fm.getDefiningMetaData(), |
| info, ctbl.uniqueConstraints()); |
| } |
| |
| /** |
| * Parse @org.apache.openjpa.persistence.jdbc.OrderColumn. |
| */ |
| private void parseOrderColumn(FieldMapping fm, OrderColumn order) { |
| if (!order.enabled()) { |
| fm.getMappingInfo().setCanOrderColumn(false); |
| return; |
| } |
| |
| Column col = new Column(); |
| if (!StringUtil.isEmpty(order.name())) |
| col.setIdentifier(DBIdentifier.newColumn(order.name(), delimit())); |
| if (!StringUtil.isEmpty(order.columnDefinition())) |
| col.setTypeIdentifier(DBIdentifier.newColumnDefinition(order.columnDefinition())); |
| if (order.precision() != 0) |
| col.setSize(order.precision()); |
| col.setFlag(Column.FLAG_UNINSERTABLE, !order.insertable()); |
| col.setFlag(Column.FLAG_UNUPDATABLE, !order.updatable()); |
| fm.getMappingInfo().setOrderColumn(col); |
| } |
| |
| /** |
| * Parse @javax.persistence.OrderColumn |
| */ |
| private void parseJavaxOrderColumn(FieldMapping fm, |
| javax.persistence.OrderColumn order) { |
| |
| Column col = new Column(); |
| if (!StringUtil.isEmpty(order.name())) |
| col.setIdentifier(DBIdentifier.newColumn(order.name(), delimit())); |
| if (!StringUtil.isEmpty(order.columnDefinition())) |
| col.setTypeIdentifier(DBIdentifier.newColumnDefinition(order.columnDefinition())); |
| col.setNotNull(!order.nullable()); |
| col.setFlag(Column.FLAG_UNINSERTABLE, !order.insertable()); |
| col.setFlag(Column.FLAG_UNUPDATABLE, !order.updatable()); |
| |
| fm.getMappingInfo().setOrderColumn(col); |
| } |
| |
| /** |
| * Parse @ElementJoinColumn(s). |
| */ |
| protected void parseElementJoinColumns(FieldMapping fm, |
| ElementJoinColumn... joins) { |
| if (joins.length == 0) |
| return; |
| |
| List<Column> cols = new ArrayList<>(joins.length); |
| int unique = 0; |
| for (int i = 0; i < joins.length; i++) { |
| cols.add(newColumn(joins[i], delimit())); |
| unique |= (joins[i].unique()) ? TRUE : FALSE; |
| } |
| setColumns(fm, fm.getElementMapping().getValueInfo(), cols, unique); |
| } |
| |
| /** |
| * Create a new schema column with information from the given annotation. |
| */ |
| private Column newColumn(ElementJoinColumn join, boolean delimit) { |
| Column col = new Column(); |
| if (!StringUtil.isEmpty(join.name())) |
| col.setIdentifier(DBIdentifier.newColumn(join.name(), delimit)); |
| if (!StringUtil.isEmpty(join.columnDefinition())) |
| col.setTypeIdentifier(DBIdentifier.newColumnDefinition(join.columnDefinition())); |
| if (!StringUtil.isEmpty(join.referencedColumnName())) |
| setTargetIdentifier(col, join.referencedColumnName()); |
| if (!StringUtil.isEmpty(join.referencedAttributeName())) |
| col.setTargetField(join.referencedAttributeName()); |
| col.setNotNull(!join.nullable()); |
| col.setFlag (Column.FLAG_UNINSERTABLE, !join.insertable ()); |
| col.setFlag (Column.FLAG_UNUPDATABLE, !join.updatable ()); |
| return col; |
| } |
| |
| /** |
| * Parse @MapKeyColumn. |
| */ |
| protected void parseMapKeyColumn(FieldMapping fm, MapKeyColumn anno) { |
| int unique = 0; |
| FieldMappingInfo info = fm.getMappingInfo(); |
| if (anno.table() != null && anno.table().length() > 0) { |
| info.setTableIdentifier(DBIdentifier.newTable(anno.table(), delimit())); |
| } |
| Column col = new Column(); |
| setupMapKeyColumn(fm, col, anno); |
| unique |= (anno.unique()) ? TRUE : FALSE; |
| setMapKeyColumn(fm, fm.getKeyMapping().getValueInfo(), col, unique); |
| } |
| |
| /** |
| * Setup the given column with information from the given annotation. |
| */ |
| private void setupMapKeyColumn(FieldMapping fm, Column col, |
| MapKeyColumn anno) { |
| if (!StringUtil.isEmpty(anno.name())) { |
| col.setIdentifier(DBIdentifier.newColumn(anno.name(), delimit())); |
| } |
| else |
| col.setIdentifier(DBIdentifier.newColumn(fm.getName() + "_" + "KEY", delimit())); |
| if (!StringUtil.isEmpty(anno.columnDefinition())) |
| col.setTypeIdentifier(DBIdentifier.newColumnDefinition(anno.columnDefinition())); |
| if (anno.precision() != 0) |
| col.setSize(anno.precision()); |
| else if (anno.length() != 255) |
| col.setSize(anno.length()); |
| col.setNotNull(!anno.nullable()); |
| col.setDecimalDigits(anno.scale()); |
| col.setFlag(Column.FLAG_UNINSERTABLE, !anno.insertable()); |
| col.setFlag(Column.FLAG_UNUPDATABLE, !anno.updatable()); |
| } |
| |
| /** |
| * Set the given map key column as the map key column for <code>fm</code>. |
| * |
| * @param unique bitwise combination of TRUE and FALSE for the |
| * unique attribute of the column |
| */ |
| protected void setMapKeyColumn(FieldMapping fm, MappingInfo info, |
| Column col, int unique) { |
| List<Column> cols = new ArrayList<>(); |
| cols.add(col); |
| info.setColumns(cols); |
| if (unique == TRUE) |
| info.setUnique(new org.apache.openjpa.jdbc.schema.Unique()); |
| } |
| |
| /** |
| * Parse @MapKeyJoinColumn(s). |
| */ |
| private void parseMapKeyJoinColumns(FieldMapping fm, |
| MapKeyJoinColumn... joins) { |
| if (joins.length == 0) |
| return; |
| |
| List<Column> cols = new ArrayList<>(joins.length); |
| int unique = 0; |
| for (int i = 0; i < joins.length; i++) { |
| cols.add(newColumn(joins[i])); |
| unique |= (joins[i].unique()) ? TRUE : FALSE; |
| } |
| setColumns(fm, fm.getKeyMapping().getValueInfo(), cols, unique); |
| } |
| |
| /** |
| * Create a new schema column with information from the given annotation. |
| */ |
| private Column newColumn(MapKeyJoinColumn join) { |
| Column col = new Column(); |
| if (!StringUtil.isEmpty(join.name())) |
| col.setIdentifier(DBIdentifier.newColumn(join.name(), delimit())); |
| if (!StringUtil.isEmpty(join.columnDefinition())) |
| col.setTypeIdentifier(DBIdentifier.newColumnDefinition(join.columnDefinition())); |
| if (!StringUtil.isEmpty(join.referencedColumnName())) |
| setTargetIdentifier(col, join.referencedColumnName()); |
| col.setNotNull(!join.nullable()); |
| col.setFlag(Column.FLAG_UNINSERTABLE, !join.insertable()); |
| col.setFlag(Column.FLAG_UNUPDATABLE, !join.updatable ()); |
| return col; |
| } |
| |
| @Override |
| protected String normalizeSequenceName(String seqName) { |
| if (StringUtil.isEmpty(seqName)) { |
| return seqName; |
| } |
| return DBIdentifier.newSequence(seqName, delimit()).getName(); |
| } |
| |
| @Override |
| protected String normalizeSchemaName(String schName) { |
| if (StringUtil.isEmpty(schName)) { |
| return schName; |
| } |
| return DBIdentifier.newSchema(schName, delimit()).getName(); |
| } |
| |
| @Override |
| protected String normalizeCatalogName(String catName) { |
| if (StringUtil.isEmpty(catName)) { |
| return catName; |
| } |
| return DBIdentifier.newCatalog(catName, delimit()).getName(); |
| } |
| |
| private boolean delimit() { |
| return _dict.getDelimitIdentifiers(); |
| } |
| } |