package org.jvnet.hyperjaxb3.ejb.strategy.customizing.impl; import java.util.ArrayList; import java.util.Collection; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.xml.namespace.QName; import org.apache.commons.lang3.Validate; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.Basic; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.CollectionProperty; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.Customizations; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.ElementCollection; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.Embeddable; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.Embedded; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.EmbeddedId; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.Entity; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.GeneratedClass; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.GeneratedId; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.GeneratedProperty; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.GeneratedVersion; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.Id; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.JaxbContext; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.ManyToMany; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.ManyToOne; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.MappedSuperclass; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.Mergeable; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.OneToMany; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.OneToOne; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.Persistence; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.SingleProperty; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.ToMany; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.ToOne; import org.jvnet.hyperjaxb3.ejb.schemas.customizations.Version; import org.jvnet.hyperjaxb3.ejb.strategy.customizing.Customizing; import org.jvnet.hyperjaxb3.jaxb2_commons.lang.MergeableMergeStrategy; import org.jvnet.hyperjaxb3.xsom.SimpleTypeAnalyzer; import org.jvnet.hyperjaxb3.xsom.TypeUtils; import org.jvnet.jaxb2_commons.lang.JAXBMergeStrategy; import org.jvnet.jaxb2_commons.lang.MergeFrom; import org.jvnet.jaxb2_commons.lang.MergeStrategy; import org.jvnet.jaxb2_commons.util.CustomizationUtils; import org.springframework.beans.factory.annotation.Required; import com.sun.java.xml.ns.persistence.orm.Column; import com.sun.tools.xjc.model.CClassInfo; import com.sun.tools.xjc.model.CCustomizable; import com.sun.tools.xjc.model.CPluginCustomization; import com.sun.tools.xjc.model.CPropertyInfo; import com.sun.tools.xjc.model.Model; import com.sun.tools.xjc.outline.ClassOutline; import com.sun.tools.xjc.outline.FieldOutline; import com.sun.xml.xsom.XSComponent; public class DefaultCustomizing implements Customizing { private final static Log logger = LogFactory.getLog(Customizations.class); private final Map<CPluginCustomization, Object> customizationsMap = new IdentityHashMap<CPluginCustomization, Object>(); private <T> T findCustomization(Model model, QName name) { final CPluginCustomization customization = CustomizationUtils .findCustomization(model, name); @SuppressWarnings("unchecked") final T t = (T) unmarshalCustomization(customization); return t; } public <T> Collection<T> findCustomizations(Model model, QName name) { final List<CPluginCustomization> customizations = CustomizationUtils .findCustomizations(model, name); return unmarshalCustomizations(customizations); } private <T> T findCustomization(CClassInfo classInfo, QName name, T defaultValue, Merge<T> merge) { final CPluginCustomization customization = CustomizationUtils .findCustomization(classInfo, name); return (T) unmarshalCustomization(customization, defaultValue, merge); } private <T> Collection<T> findCustomizations(CClassInfo classInfo, QName name) { final List<CPluginCustomization> customizations = CustomizationUtils .findCustomizations(classInfo, name); return unmarshalCustomizations(customizations); } private <T> T findCustomization(CPropertyInfo propertyInfo, QName name, T defaultValue, Merge<T> merge) { final CPluginCustomization customization = CustomizationUtils .findCustomization(propertyInfo, name); final T t = (T) unmarshalCustomization(customization, defaultValue, merge); return t; } @SuppressWarnings("unchecked") private <T> T findCustomization(CPropertyInfo propertyInfo, QName name) { final CPluginCustomization customization = CustomizationUtils .findCustomization(propertyInfo, name); final T t = (T) unmarshalCustomization(customization); return t; } public void addCustomization(CCustomizable customizable, QName name, Object customization) { final CPluginCustomization pluginCustomization = CustomizationUtils .addCustomization(customizable, Customizations.getContext(), name, customization); this.customizationsMap.put(pluginCustomization, customization); } private <T> Collection<T> unmarshalCustomizations( final Collection<CPluginCustomization> customizations) throws AssertionError { final List<T> unmarshalledCustomizations = new ArrayList<T>( customizations.size()); for (CPluginCustomization customization : customizations) { unmarshalledCustomizations.add(this.<T> unmarshalCustomization( customization, null, null)); } return unmarshalledCustomizations; } @SuppressWarnings("unchecked") private <T> T unmarshalCustomization( final CPluginCustomization customization, T defaultValue, Merge<T> merge) throws AssertionError { if (customization == null) { return null; } else { final T value = (T) this.customizationsMap.get(customization); if (value != null) { // return value instanceof CopyTo ? (T) ((CopyTo) value) // .copyTo(((CopyTo) value).createNewInstance()) : value; return value; } else { final T t = (T) CustomizationUtils.unmarshall( Customizations.getContext(), customization); if (defaultValue != null) { Validate.notNull(merge); merge.merge(t, defaultValue); } this.customizationsMap.put(customization, t); return t; // return t instanceof CopyTo ? (T) ((CopyTo) t) // .copyTo(((CopyTo) t).createNewInstance()) : t; } } } private <T> T unmarshalCustomization( final CPluginCustomization customization) throws AssertionError { T t = (T) unmarshalCustomization(customization, (T) null, null); return t; } private Persistence defaultCustomizations; public Persistence getDefaultCustomizations() { return defaultCustomizations; } @Required public void setDefaultCustomizations(Persistence defaultCustomization) { this.defaultCustomizations = defaultCustomization; } public Persistence getModelCustomization(Model model) { final Persistence cPersistence = findCustomization(model, Customizations.PERSISTENCE_ELEMENT_NAME); if (cPersistence == null) { return getDefaultCustomizations(); } if (!cPersistence.isMerge()) { return cPersistence; } else { final Persistence defaultPersistence = getDefaultCustomizations(); if (cPersistence.getDefaultManyToOne() != null) { if (cPersistence.getDefaultManyToOne().getJoinTable() != null) { defaultPersistence.getDefaultManyToOne().getJoinColumn() .clear(); } else if (!cPersistence.getDefaultManyToOne().getJoinColumn() .isEmpty()) { defaultPersistence.getDefaultManyToOne().setJoinTable(null); } } if (cPersistence.getDefaultOneToOne() != null) { if (cPersistence.getDefaultOneToOne().getJoinTable() != null) { defaultPersistence.getDefaultOneToOne().getJoinColumn() .clear(); } else if (!cPersistence.getDefaultOneToOne().getJoinColumn() .isEmpty()) { defaultPersistence.getDefaultOneToOne().setJoinTable(null); } } if (cPersistence.getDefaultOneToMany() != null) { if (cPersistence.getDefaultOneToMany().getJoinTable() != null) { defaultPersistence.getDefaultOneToMany().getJoinColumn() .clear(); } else if (!cPersistence.getDefaultOneToMany().getJoinColumn() .isEmpty()) { defaultPersistence.getDefaultOneToMany().setJoinTable(null); } } cPersistence.getDefaultSingleProperty().addAll( defaultPersistence.getDefaultSingleProperty()); cPersistence.getDefaultCollectionProperty().addAll( defaultPersistence.getDefaultCollectionProperty()); mergeFrom(cPersistence, defaultPersistence); return cPersistence; } } public GeneratedId getGeneratedId(CClassInfo classInfo) { final Persistence persistence = getModelCustomization(classInfo); if (persistence.getDefaultGeneratedId() == null) { throw new AssertionError("Default id element is not provided."); } final GeneratedId defaultId = (GeneratedId) persistence .getDefaultGeneratedId().copyTo(new GeneratedId()); final GeneratedId id; if (CustomizationUtils.containsCustomization(classInfo, Customizations.GENERATED_ID_ELEMENT_NAME)) { id = findCustomization(classInfo, Customizations.GENERATED_ID_ELEMENT_NAME, defaultId, this.<GeneratedId> merge()); } else { id = defaultId; } return id; } public GeneratedClass getGeneratedClass(CPropertyInfo propertyInfo) { final GeneratedClass generatedClass; if (CustomizationUtils.containsCustomization(propertyInfo, Customizations.GENERATED_CLASS_ELEMENT_NAME)) { generatedClass = findCustomization(propertyInfo, Customizations.GENERATED_CLASS_ELEMENT_NAME); } else { generatedClass = null; } return generatedClass; } public GeneratedProperty getGeneratedProperty(CPropertyInfo propertyInfo) { final GeneratedProperty generatedProperty; if (CustomizationUtils.containsCustomization(propertyInfo, Customizations.GENERATED_PROPERTY_ELEMENT_NAME)) { generatedProperty = findCustomization(propertyInfo, Customizations.GENERATED_PROPERTY_ELEMENT_NAME); } else { generatedProperty = getGeneratedProperty( (CClassInfo) propertyInfo.parent(), propertyInfo.getName(true)); } return generatedProperty; } public GeneratedProperty getGeneratedProperty(CClassInfo classInfo, String propertyName) { GeneratedProperty generatedProperty = null; if (classInfo != null && CustomizationUtils.containsCustomization(classInfo, Customizations.GENERATED_PROPERTY_ELEMENT_NAME)) { final Collection<GeneratedProperty> generatedProperties; generatedProperties = findCustomizations(classInfo, Customizations.GENERATED_PROPERTY_ELEMENT_NAME); for (GeneratedProperty p : generatedProperties) { if (propertyName.equals(p.getName())) { generatedProperty = p; } } } return generatedProperty; } public Id getId(CPropertyInfo property) { final Persistence persistence = getModelCustomization(property); if (persistence.getDefaultId() == null) { throw new AssertionError("Default id element is not provided."); } final Id defaultId = (Id) persistence.getDefaultId().copyTo(new Id()); final Id id; if (CustomizationUtils.containsCustomization(property, Customizations.ID_ELEMENT_NAME)) { id = findCustomization(property, Customizations.ID_ELEMENT_NAME, defaultId, this.<Id> merge()); } else { id = defaultId; } return id; } public Id getId(FieldOutline property) { return getId(property.getPropertyInfo()); } public EmbeddedId getEmbeddedId(CPropertyInfo property) { final Persistence persistence = getModelCustomization(property); if (persistence.getDefaultEmbeddedId() == null) { throw new AssertionError( "Default embedded id element is not provided."); } final EmbeddedId defaultId = (EmbeddedId) persistence .getDefaultEmbeddedId().copyTo(new EmbeddedId()); final EmbeddedId id; if (CustomizationUtils.containsCustomization(property, Customizations.EMBEDDED_ID_ELEMENT_NAME)) { id = findCustomization(property, Customizations.EMBEDDED_ID_ELEMENT_NAME, defaultId, this.<EmbeddedId> merge()); } else { id = defaultId; } return id; } public EmbeddedId getEmbeddedId(FieldOutline property) { return getEmbeddedId(property.getPropertyInfo()); } public Version getVersion(CPropertyInfo property) { final Persistence persistence = getModelCustomization(property); if (persistence.getDefaultVersion() == null) { throw new AssertionError("Default version element is not provided."); } final Version defaultVersion = (Version) persistence .getDefaultVersion().copyTo(new Version()); final Version version; if (CustomizationUtils.containsCustomization(property, Customizations.VERSION_ELEMENT_NAME)) { version = findCustomization(property, Customizations.VERSION_ELEMENT_NAME, defaultVersion, this.<Version> merge()); } else { version = defaultVersion; } return version; } public Version getVersion(FieldOutline property) { return getVersion(property.getPropertyInfo()); } public GeneratedVersion getGeneratedVersion(CClassInfo classInfo) { final Persistence persistence = getModelCustomization(classInfo); if (persistence.getDefaultGeneratedVersion() == null) { throw new AssertionError( "Default generated version element is not provided."); } final GeneratedVersion defaultGeneratedVersion = (GeneratedVersion) persistence .getDefaultGeneratedVersion().copyTo(new GeneratedVersion()); final GeneratedVersion generatedVersion; if (CustomizationUtils.containsCustomization(classInfo, Customizations.GENERATED_VERSION_ELEMENT_NAME)) { generatedVersion = findCustomization(classInfo, Customizations.GENERATED_VERSION_ELEMENT_NAME, defaultGeneratedVersion, this.<GeneratedVersion> merge()); } else { generatedVersion = defaultGeneratedVersion.isForced() ? defaultGeneratedVersion : null; } return generatedVersion; } public Basic getDefaultBasic(CPropertyInfo property) throws AssertionError { final Persistence persistence = getModelCustomization(property); if (persistence.getDefaultBasic() == null) { throw new AssertionError("Default basic element is not provided."); } final Basic defaultBasic; final XSComponent schemaComponent = property.getSchemaComponent(); if (schemaComponent == null) { defaultBasic = (Basic) persistence.getDefaultBasic().copyTo( new Basic()); } else { final List<QName> typeNames = TypeUtils .getTypeNames(schemaComponent); Basic basic = null; for (Iterator<QName> typeNameIterator = typeNames.iterator(); typeNameIterator .hasNext() && basic == null;) { final QName typeName = typeNameIterator.next(); final SingleProperty singleProperty = getDefaultSingleProperty( persistence, typeName); if (singleProperty != null) { if (singleProperty.getBasic() != null) { basic = singleProperty.getBasic(); } else { logger.warn("Default single property for type [" + typeName + "] does not define the expected basic mapping."); } } } if (basic == null) { defaultBasic = (Basic) persistence.getDefaultBasic().copyTo( new Basic()); } else { defaultBasic = (Basic) basic.copyTo(new Basic()); mergeFrom(defaultBasic, (Basic) persistence.getDefaultBasic() .copyTo(new Basic())); } } final Column column = defaultBasic.getColumn(); if (column != null) { assignColumn$LengthPrecisionScale(property, column); } return defaultBasic; } private void assignColumn$LengthPrecisionScale(CPropertyInfo property, final Column column) { final Integer length = createColumn$Length(property); if (length != null) { column.setLength(length); } final Integer precision = createColumn$Precision(property); final Integer scale = createColumn$Scale(property); if (precision != null && precision.intValue() != 0) { column.setPrecision(precision); } else { if (scale != null && scale.intValue() != 0) { final Integer defaultPrecision = column.getPrecision(); if (defaultPrecision != null) { final Integer defaultScale = column.getScale(); final int integerDigits = defaultPrecision - (defaultScale == null ? 0 : defaultScale .intValue()); column.setPrecision(integerDigits + scale.intValue()); column.setScale(scale); } } } if (scale != null && scale.intValue() != 0) { column.setScale(scale); } } public ElementCollection getDefaultElementCollection(CPropertyInfo property) throws AssertionError { final Persistence persistence = getModelCustomization(property); if (persistence.getDefaultElementCollection() == null) { throw new AssertionError( "Default element collection element is not provided."); } final ElementCollection defaultItem; final XSComponent schemaComponent = property.getSchemaComponent(); if (schemaComponent == null) { defaultItem = (ElementCollection) persistence .getDefaultElementCollection().copyTo( new ElementCollection()); } else { final List<QName> typeNames = TypeUtils .getTypeNames(schemaComponent); ElementCollection item = null; for (Iterator<QName> typeNameIterator = typeNames.iterator(); typeNameIterator .hasNext() && item == null;) { final QName typeName = typeNameIterator.next(); final CollectionProperty collectionProperty = getDefaultCollectionProperty( persistence, typeName); if (collectionProperty != null) { if (collectionProperty.getElementCollection() != null) { item = collectionProperty.getElementCollection(); } else { logger.warn("Default single property for type [" + typeName + "] does not define the expected basic mapping."); } } } if (item == null) { defaultItem = (ElementCollection) persistence .getDefaultElementCollection().copyTo( new ElementCollection()); } else { defaultItem = (ElementCollection) item .copyTo(new ElementCollection()); mergeFrom( defaultItem, (ElementCollection) persistence .getDefaultElementCollection().copyTo( new ElementCollection())); } } if (defaultItem.getColumn() != null) { assignColumn$LengthPrecisionScale(property, defaultItem.getColumn()); } return defaultItem; } public SingleProperty getDefaultSingleProperty(Persistence persistence, QName typeName) { Validate.notNull(persistence); Validate.notNull(typeName); for (final SingleProperty property : persistence .getDefaultSingleProperty()) { if (typeName.equals(property.getType())) { return property; } } return null; } public CollectionProperty getDefaultCollectionProperty( Persistence persistence, QName typeName) { Validate.notNull(persistence); Validate.notNull(typeName); for (final CollectionProperty property : persistence .getDefaultCollectionProperty()) { if (typeName.equals(property.getType())) { return property; } } return null; } public Basic getBasic(CPropertyInfo property) { final Basic defaultBasic = getDefaultBasic(property); final Basic basic; if (CustomizationUtils.containsCustomization(property, Customizations.BASIC_ELEMENT_NAME)) { basic = findCustomization(property, Customizations.BASIC_ELEMENT_NAME, defaultBasic, this.<Basic> merge()); } else { basic = defaultBasic; } return basic; } public Integer createColumn$Scale(CPropertyInfo property) { final Integer scale; final Long fractionDigits = SimpleTypeAnalyzer .getFractionDigits(property.getSchemaComponent()); final Long totalDigits = SimpleTypeAnalyzer.getTotalDigits(property .getSchemaComponent()); if (fractionDigits != null) { scale = fractionDigits.intValue(); } else if (totalDigits != null) { scale = totalDigits.intValue(); } else { scale = null; } return scale; } public Integer createColumn$Precision(CPropertyInfo property) { final Integer precision; final Long totalDigits = SimpleTypeAnalyzer.getTotalDigits(property .getSchemaComponent()); final Long fractionDigits = SimpleTypeAnalyzer .getFractionDigits(property.getSchemaComponent()); if (totalDigits != null) { if (fractionDigits != null) { precision = totalDigits.intValue() + fractionDigits.intValue(); } else { precision = totalDigits.intValue() * 2; } } else { precision = null; } return precision; } public Integer createColumn$Length(CPropertyInfo property) { final Integer finalLength; final Long length = SimpleTypeAnalyzer.getLength(property .getSchemaComponent()); if (length != null) { finalLength = length.intValue(); } else { final Long maxLength = SimpleTypeAnalyzer.getMaxLength(property .getSchemaComponent()); if (maxLength != null) { finalLength = maxLength.intValue(); } else { final Long minLength = SimpleTypeAnalyzer.getMinLength(property .getSchemaComponent()); if (minLength != null) { int intMinLength = minLength.intValue(); if (intMinLength > 127) { finalLength = intMinLength * 2; } else { finalLength = null; } } else { finalLength = null; } } } return finalLength; } public Basic getBasic(FieldOutline fieldOutline) { return getBasic(fieldOutline.getPropertyInfo()); } public OneToMany getOneToMany(CPropertyInfo property) { final OneToMany coneToMany; final Persistence persistence = getModelCustomization(property); if (persistence.getDefaultOneToMany() == null) { throw new AssertionError( "Default one-to-many element is not provided."); } final OneToMany defaultOneToMany = (OneToMany) persistence .getDefaultOneToMany().copyTo(new OneToMany()); if (CustomizationUtils.containsCustomization(property, Customizations.ONE_TO_MANY_ELEMENT_NAME)) { coneToMany = findCustomization(property, Customizations.ONE_TO_MANY_ELEMENT_NAME, defaultOneToMany, new Merge<OneToMany>() { public void merge(OneToMany value, OneToMany defaultValue) { DefaultCustomizing.this.merge(value, defaultValue); } }); } else { return defaultOneToMany; } return coneToMany; } private void merge(final OneToMany cOneToMany, final OneToMany defaultOneToMany) { if (cOneToMany.isMerge()) { if (cOneToMany.getJoinTable() != null) { defaultOneToMany.getJoinColumn().clear(); } else if (!cOneToMany.getJoinColumn().isEmpty()) { defaultOneToMany.setJoinTable(null); } if (cOneToMany.getOrderBy() != null) { defaultOneToMany.setOrderColumn(null); } else if (cOneToMany.getOrderColumn() != null) { defaultOneToMany.setOrderBy(null); } mergeFrom(cOneToMany, defaultOneToMany); } } private void merge(final Embedded cEmbedded, final Embedded defaultEmbedded) { mergeFrom(cEmbedded, defaultEmbedded); } public Persistence getModelCustomization(CPropertyInfo property) { final CClassInfo classInfo = (CClassInfo) property.parent(); return getModelCustomization(classInfo); } public Persistence getModelCustomization(final CClassInfo classInfo) { final Persistence persistence = getModelCustomization(classInfo.model); return persistence; } public OneToMany getOneToMany(FieldOutline property) { return getOneToMany(property.getPropertyInfo()); } public ManyToOne getManyToOne(CPropertyInfo property) { final Persistence persistence = getModelCustomization(property); if (persistence.getDefaultManyToOne() == null) { // TODO throw new AssertionError( "Default many-to-one element is not provided."); } final ManyToOne defaultManyToOne = (ManyToOne) persistence .getDefaultManyToOne().copyTo(new ManyToOne()); final ManyToOne cmanyToOne; if (CustomizationUtils.containsCustomization(property, Customizations.MANY_TO_ONE_ELEMENT_NAME)) { cmanyToOne = findCustomization(property, Customizations.MANY_TO_ONE_ELEMENT_NAME, defaultManyToOne, new Merge<ManyToOne>() { public void merge(ManyToOne value, ManyToOne defaultValue) { DefaultCustomizing.this.merge(value, defaultValue); } }); } else { return defaultManyToOne; } return cmanyToOne; } private void merge(final ManyToOne cManyToOne, final ManyToOne defaultManyToOne) { if (cManyToOne.isMerge()) { if (cManyToOne.getJoinTable() != null) { defaultManyToOne.getJoinColumn().clear(); } else if (!cManyToOne.getJoinColumn().isEmpty()) { defaultManyToOne.setJoinTable(null); } mergeFrom(cManyToOne, defaultManyToOne); } } public ManyToOne getManyToOne(FieldOutline property) { return getManyToOne(property.getPropertyInfo()); } public OneToOne getOneToOne(CPropertyInfo property) { final Persistence persistence = getModelCustomization(property); if (persistence.getDefaultOneToOne() == null) { // TODO throw new AssertionError( "Default one-to-one element is not provided."); } final OneToOne defaultOneToOne = (OneToOne) persistence .getDefaultOneToOne().copyTo(new OneToOne()); final OneToOne cOneToOne; if (CustomizationUtils.containsCustomization(property, Customizations.ONE_TO_ONE_ELEMENT_NAME)) { cOneToOne = findCustomization(property, Customizations.ONE_TO_ONE_ELEMENT_NAME, defaultOneToOne, new Merge<OneToOne>() { public void merge(OneToOne value, OneToOne defaultValue) { DefaultCustomizing.this.merge(value, defaultValue); } }); } else { return defaultOneToOne; } return cOneToOne; } private void merge(final OneToOne cOneToOne, final OneToOne defaultOneToOne) { if (cOneToOne.isMerge()) { if (cOneToOne.getJoinTable() != null) { defaultOneToOne.getJoinColumn().clear(); } else if (!cOneToOne.getJoinColumn().isEmpty()) { defaultOneToOne.setJoinTable(null); } mergeFrom(cOneToOne, defaultOneToOne); } } public OneToOne getOneToOne(FieldOutline property) { return getOneToOne(property.getPropertyInfo()); } public ManyToMany getManyToMany(CPropertyInfo property) { final Persistence persistence = getModelCustomization(property); if (persistence.getDefaultManyToMany() == null) { // TODO throw new AssertionError( "Default many-to-many element is not provided."); } final ManyToMany defaultManyToMany = (ManyToMany) persistence .getDefaultManyToMany().copyTo(new ManyToMany()); final ManyToMany cManyToMany; if (CustomizationUtils.containsCustomization(property, Customizations.MANY_TO_MANY_ELEMENT_NAME)) { cManyToMany = findCustomization(property, Customizations.MANY_TO_MANY_ELEMENT_NAME, defaultManyToMany, new Merge<ManyToMany>() { public void merge(ManyToMany value, ManyToMany defaultValue) { DefaultCustomizing.this.merge(value, defaultValue); } }); } else { return defaultManyToMany; } return cManyToMany; } private void merge(final ManyToMany source, final ManyToMany defaultSource) { if (source.isMerge()) { if (source.getOrderBy() != null) { defaultSource.setOrderColumn(null); } else if (source.getOrderColumn() != null) { defaultSource.setOrderBy(null); } mergeFrom(source, defaultSource); } } public ElementCollection getElementCollection(FieldOutline fieldOutline) { return getElementCollection(fieldOutline.getPropertyInfo()); } public ElementCollection getElementCollection(CPropertyInfo property) { final ElementCollection defaultItem = getDefaultElementCollection(property); final ElementCollection item; if (CustomizationUtils.containsCustomization(property, Customizations.ELEMENT_COLLECTION_ELEMENT_NAME)) { item = findCustomization(property, Customizations.ELEMENT_COLLECTION_ELEMENT_NAME, defaultItem, this.<ElementCollection> merge()); } else { item = defaultItem; } return item; } public ManyToMany getManyToMany(FieldOutline property) { return getManyToMany(property.getPropertyInfo()); } public Entity getEntity(ClassOutline classOutline) { return getEntity(classOutline.target); } public Entity getEntity(CClassInfo classInfo) { final Persistence persistence = getModelCustomization(classInfo); if (persistence.getDefaultEntity() == null) { // TODO throw new AssertionError("Default entity element is not provided."); } final Entity defaultEntity = (Entity) persistence.getDefaultEntity() .copyTo(new Entity()); final Entity cEntity; if (CustomizationUtils.containsCustomization(classInfo, Customizations.ENTITY_ELEMENT_NAME)) { cEntity = findCustomization(classInfo, Customizations.ENTITY_ELEMENT_NAME, defaultEntity, this.<Entity> merge()); } else { addCustomization(classInfo, Customizations.ENTITY_ELEMENT_NAME, defaultEntity); return defaultEntity; } return cEntity; } public Object getToMany(FieldOutline property) { return getToMany(property.getPropertyInfo()); } public Object getToOne(FieldOutline property) { return getToOne(property.getPropertyInfo()); } public Object getToOne(CPropertyInfo property) { final Persistence persistence = getModelCustomization(property); if (CustomizationUtils.containsCustomization(property, Customizations.MANY_TO_ONE_ELEMENT_NAME)) { return getManyToOne(property); } else if (CustomizationUtils.containsCustomization(property, Customizations.ONE_TO_ONE_ELEMENT_NAME)) { return getOneToOne(property); } if (CustomizationUtils.containsCustomization(property, Customizations.EMBEDDED_ELEMENT_NAME)) { return getEmbedded(property); } else { final ToOne defaultToOne = (ToOne) persistence.getDefaultToOne() .copyTo(new ToOne()); if (defaultToOne.getOneToOne() != null) { final OneToOne cOneToOne = defaultToOne.getOneToOne(); final OneToOne defaultOneToOne = persistence .getDefaultOneToOne(); if (defaultOneToOne == null) { throw new AssertionError( "Default One-to-one element is not provided."); } merge(cOneToOne, defaultOneToOne); return cOneToOne; } else if (defaultToOne.getManyToOne() != null) { final ManyToOne cManyToOne = defaultToOne.getManyToOne(); final ManyToOne defaultManyToOne = persistence .getDefaultManyToOne(); if (defaultManyToOne == null) { throw new AssertionError( "Default many-to-one element is not provided."); } merge(cManyToOne, defaultManyToOne); return cManyToOne; } else if (defaultToOne.getEmbedded() != null) { final Embedded cEmbedded = defaultToOne.getEmbedded(); final Embedded defaultEmbedded = persistence .getDefaultEmbedded(); if (defaultEmbedded == null) { throw new AssertionError( "Default embedded element is not provided."); } merge(cEmbedded, defaultEmbedded); return cEmbedded; } else { throw new AssertionError( "Either one-to-one or many-to-one elements must be provided in the default-to-one element."); } } } public Object getToMany(CPropertyInfo property) { final Persistence persistence = getModelCustomization(property); if (CustomizationUtils.containsCustomization(property, Customizations.MANY_TO_MANY_ELEMENT_NAME)) { return getManyToMany(property); } else if (CustomizationUtils.containsCustomization(property, Customizations.ONE_TO_MANY_ELEMENT_NAME)) { return getOneToMany(property); } else { final ToMany defaultToMany = (ToMany) persistence .getDefaultToMany().copyTo(new ToMany()); if (defaultToMany.getOneToMany() != null) { final OneToMany cOneToMany = defaultToMany.getOneToMany(); final OneToMany defaultOneToMany = persistence .getDefaultOneToMany(); if (defaultOneToMany == null) { throw new AssertionError( "Default one-to-many element is not provided."); } merge(cOneToMany, defaultOneToMany); return cOneToMany; } else if (defaultToMany.getManyToMany() != null) { final ManyToMany cManyToMany = defaultToMany.getManyToMany(); final ManyToMany defaultManyToMany = persistence .getDefaultManyToMany(); if (defaultManyToMany == null) { throw new AssertionError( "Default many-to-many element is not provided."); } merge(cManyToMany, defaultManyToMany); return cManyToMany; } else { throw new AssertionError( "Either one-to-many or many-to-many elements must be provided in the default-to-many element."); } } } public MappedSuperclass getMappedSuperclass(ClassOutline classOutline) { return getMappedSuperclass(classOutline.target); } public MappedSuperclass getMappedSuperclass(CClassInfo classInfo) { final Persistence persistence = getModelCustomization(classInfo); if (persistence.getDefaultMappedSuperclass() == null) { // TODO throw new AssertionError( "Default mapped superclass element is not provided."); } final MappedSuperclass defaultMappedSuperclass = (MappedSuperclass) persistence .getDefaultMappedSuperclass().copyTo(new MappedSuperclass()); final MappedSuperclass cMappedSuperclass; if (CustomizationUtils.containsCustomization(classInfo, Customizations.MAPPED_SUPERCLASS_ELEMENT_NAME)) { cMappedSuperclass = findCustomization(classInfo, Customizations.MAPPED_SUPERCLASS_ELEMENT_NAME, defaultMappedSuperclass, this.<MappedSuperclass> merge()); } else { return defaultMappedSuperclass; } return cMappedSuperclass; } public Object getEntityOrMappedSuperclassOrEmbeddable( ClassOutline classOutline) { return getEntityOrMappedSuperclassOrEmbeddable(classOutline.target); } public Object getEntityOrMappedSuperclassOrEmbeddable(CClassInfo classInfo) { // final Persistence persistence = getModelCustomization(classInfo); if (CustomizationUtils.containsCustomization(classInfo, Customizations.ENTITY_ELEMENT_NAME)) { return getEntity(classInfo); } else if (CustomizationUtils.containsCustomization(classInfo, Customizations.MAPPED_SUPERCLASS_ELEMENT_NAME)) { return getMappedSuperclass(classInfo); } else if (CustomizationUtils.containsCustomization(classInfo, Customizations.EMBEDDABLE_ELEMENT_NAME)) { return getEmbeddable(classInfo); } else { // Default is entity return getEntity(classInfo); } } public Embeddable getEmbeddable(CClassInfo classInfo) { final Persistence persistence = getModelCustomization(classInfo); if (persistence.getDefaultEmbeddable() == null) { // TODO throw new AssertionError( "Default embeddable element is not provided."); } final Embeddable defaultEmbeddable = (Embeddable) persistence .getDefaultEmbeddable().copyTo(new Embeddable()); final Embeddable cEmbeddable; if (CustomizationUtils.containsCustomization(classInfo, Customizations.EMBEDDABLE_ELEMENT_NAME)) { cEmbeddable = findCustomization(classInfo, Customizations.EMBEDDABLE_ELEMENT_NAME, defaultEmbeddable, this.<Embeddable> merge()); } else { return defaultEmbeddable; } return cEmbeddable; } public Embeddable getEmbeddable(ClassOutline classOutline) { return getEmbeddable(classOutline.target); } public Embedded getEmbedded(CPropertyInfo property) { final Persistence persistence = getModelCustomization(property); if (persistence.getDefaultEmbedded() == null) { throw new AssertionError( "Default embedded element is not provided."); } final Embedded defaultEmbedded = (Embedded) persistence .getDefaultEmbedded().copyTo(new Embedded()); final Embedded embedded; if (CustomizationUtils.containsCustomization(property, Customizations.EMBEDDED_ELEMENT_NAME)) { embedded = findCustomization(property, Customizations.EMBEDDED_ELEMENT_NAME, defaultEmbedded, this.<Embedded> merge()); } else { embedded = defaultEmbedded; } return embedded; } public Embedded getEmbedded(FieldOutline property) { return getEmbedded(property.getPropertyInfo()); } public JaxbContext getJaxbContext(FieldOutline property) { return getJaxbContext(property.getPropertyInfo()); } public JaxbContext getJaxbContext(CPropertyInfo property) { final Persistence persistence = getModelCustomization(property); if (persistence.getDefaultJaxbContext() == null) { throw new AssertionError( "Default jaxb-context element is not provided."); } final JaxbContext defaultJaxbContext = (JaxbContext) persistence .getDefaultJaxbContext().copyTo(new JaxbContext()); final JaxbContext jaxbContext; if (CustomizationUtils.containsCustomization(property, Customizations.JAXB_CONTEXT_ELEMENT_NAME)) { jaxbContext = findCustomization(property, Customizations.JAXB_CONTEXT_ELEMENT_NAME, defaultJaxbContext, this.<JaxbContext> merge()); } else { jaxbContext = defaultJaxbContext; } return jaxbContext; } private final static MergeStrategy MERGE_STRATEGY = new MergeableMergeStrategy( JAXBMergeStrategy.INSTANCE); private <T extends Mergeable & MergeFrom> void mergeFrom(T value, T defaultValue) { value.mergeFrom(null, null, value, defaultValue, MERGE_STRATEGY); } private interface Merge<M> { public void merge(M value, M defaultValue); } private <M extends Mergeable & MergeFrom> Merge<M> merge() { return new Merge<M>() { public void merge(M value, M defaultValue) { DefaultCustomizing.this.mergeFrom(value, defaultValue); } }; } }