/******************************************************************************* * Copyright (c) 2006, 2010 Oracle. All rights reserved. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0, which accompanies this distribution * and is available at http://www.eclipse.org/legal/epl-v10.html. * * Contributors: * Oracle - initial API and implementation ******************************************************************************/ package org.eclipse.jpt.jpa.core.internal.context.java; import java.util.Iterator; import java.util.List; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jpt.common.utility.Filter; import org.eclipse.jpt.common.utility.internal.Association; import org.eclipse.jpt.common.utility.internal.SimpleAssociation; import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable; import org.eclipse.jpt.jpa.core.JpaFactory; import org.eclipse.jpt.jpa.core.MappingKeys; import org.eclipse.jpt.jpa.core.context.BaseColumn; import org.eclipse.jpt.jpa.core.context.Converter; import org.eclipse.jpt.jpa.core.context.FetchType; import org.eclipse.jpt.jpa.core.context.NamedColumn; import org.eclipse.jpt.jpa.core.context.java.JavaBasicMapping; import org.eclipse.jpt.jpa.core.context.java.JavaColumn; import org.eclipse.jpt.jpa.core.context.java.JavaConverter; import org.eclipse.jpt.jpa.core.context.java.JavaEnumeratedConverter; import org.eclipse.jpt.jpa.core.context.java.JavaLobConverter; import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute; import org.eclipse.jpt.jpa.core.context.java.JavaTemporalConverter; import org.eclipse.jpt.jpa.core.internal.context.BaseColumnTextRangeResolver; import org.eclipse.jpt.jpa.core.internal.context.JptValidator; import org.eclipse.jpt.jpa.core.internal.context.NamedColumnTextRangeResolver; import org.eclipse.jpt.jpa.core.internal.jpa1.context.EntityTableDescriptionProvider; import org.eclipse.jpt.jpa.core.internal.jpa1.context.NamedColumnValidator; import org.eclipse.jpt.jpa.core.internal.jpa1.context.java.NullJavaConverter; import org.eclipse.jpt.jpa.core.resource.java.Annotation; import org.eclipse.jpt.jpa.core.resource.java.BasicAnnotation; import org.eclipse.jpt.jpa.core.resource.java.ColumnAnnotation; import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentAttribute; import org.eclipse.wst.validation.internal.provisional.core.IMessage; import org.eclipse.wst.validation.internal.provisional.core.IReporter; /** * Java basic mapping */ public abstract class AbstractJavaBasicMapping extends AbstractJavaAttributeMapping implements JavaBasicMapping { protected final JavaColumn column; protected FetchType specifiedFetch; protected FetchType defaultFetch; protected Boolean specifiedOptional; protected boolean defaultOptional; protected JavaConverter converter; // never null protected static final JavaConverter.Adapter[] CONVERTER_ADAPTER_ARRAY = new JavaConverter.Adapter[] { JavaEnumeratedConverter.Adapter.instance(), JavaTemporalConverter.Adapter.instance(), JavaLobConverter.Adapter.instance() }; protected static final Iterable CONVERTER_ADAPTERS = new ArrayIterable(CONVERTER_ADAPTER_ARRAY); protected AbstractJavaBasicMapping(JavaPersistentAttribute parent) { super(parent); this.column = this.buildColumn(); this.specifiedFetch = this.buildSpecifiedFetch(); this.specifiedOptional = this.buildSpecifiedOptional(); this.converter = this.buildConverter(); } // ********** synchronize/update ********** @Override public void synchronizeWithResourceModel() { super.synchronizeWithResourceModel(); this.column.synchronizeWithResourceModel(); this.setSpecifiedFetch_(this.buildSpecifiedFetch()); this.setSpecifiedOptional_(this.buildSpecifiedOptional()); this.syncConverter(); } @Override public void update() { super.update(); this.column.update(); this.setDefaultFetch(this.buildDefaultFetch()); this.setDefaultOptional(this.buildDefaultOptional()); this.converter.update(); } // ********** column ********** public JavaColumn getColumn() { return this.column; } protected JavaColumn buildColumn() { return this.getJpaFactory().buildJavaColumn(this, this); } // ********** fetch ********** public FetchType getFetch() { return (this.specifiedFetch != null) ? this.specifiedFetch : this.defaultFetch; } public FetchType getSpecifiedFetch() { return this.specifiedFetch; } public void setSpecifiedFetch(FetchType fetch) { if (this.valuesAreDifferent(fetch, this.specifiedFetch)) { this.getAnnotationForUpdate().setFetch(FetchType.toJavaResourceModel(fetch)); this.setSpecifiedFetch_(fetch); } } protected void setSpecifiedFetch_(FetchType fetch) { FetchType old = this.specifiedFetch; this.specifiedFetch = fetch; this.firePropertyChanged(SPECIFIED_FETCH_PROPERTY, old, fetch); } protected FetchType buildSpecifiedFetch() { BasicAnnotation annotation = this.getMappingAnnotation(); return (annotation == null) ? null : FetchType.fromJavaResourceModel(annotation.getFetch()); } public FetchType getDefaultFetch() { return this.defaultFetch; } protected void setDefaultFetch(FetchType fetch) { FetchType old = this.defaultFetch; this.defaultFetch = fetch; this.firePropertyChanged(DEFAULT_FETCH_PROPERTY, old, fetch); } protected FetchType buildDefaultFetch() { return DEFAULT_FETCH_TYPE; } // ********** optional ********** public boolean isOptional() { return (this.specifiedOptional != null) ? this.specifiedOptional.booleanValue() : this.isDefaultOptional(); } public Boolean getSpecifiedOptional() { return this.specifiedOptional; } public void setSpecifiedOptional(Boolean optional) { if (this.valuesAreDifferent(optional, this.specifiedOptional)) { this.getAnnotationForUpdate().setOptional(optional); this.setSpecifiedOptional_(optional); } } protected void setSpecifiedOptional_(Boolean optional) { Boolean old = this.specifiedOptional; this.specifiedOptional = optional; this.firePropertyChanged(SPECIFIED_OPTIONAL_PROPERTY, old, optional); } protected Boolean buildSpecifiedOptional() { BasicAnnotation annotation = this.getMappingAnnotation(); return (annotation == null) ? null : annotation.getOptional(); } public boolean isDefaultOptional() { return defaultOptional; } protected void setDefaultOptional(boolean optional) { boolean old = this.defaultOptional; this.defaultOptional = optional; this.firePropertyChanged(DEFAULT_OPTIONAL_PROPERTY, old, optional); } protected boolean buildDefaultOptional() { return DEFAULT_OPTIONAL; } // ********** converter ********** public JavaConverter getConverter() { return this.converter; } public void setConverter(Class converterType) { if (this.converter.getType() != converterType) { this.converter.dispose(); JavaConverter.Adapter converterAdapter = this.getConverterAdapter(converterType); this.retainConverterAnnotation(converterAdapter); this.setConverter_(this.buildConverter(converterAdapter)); } } protected JavaConverter buildConverter(JavaConverter.Adapter converterAdapter) { return (converterAdapter != null) ? converterAdapter.buildNewConverter(this, this.getJpaFactory()) : this.buildNullConverter(); } protected void setConverter_(JavaConverter converter) { Converter old = this.converter; this.converter = converter; this.firePropertyChanged(CONVERTER_PROPERTY, old, converter); } /** * Clear all the converter annotations except for the annotation * corresponding to the specified adapter. If the specified adapter is * null, remove all the converter annotations. */ protected void retainConverterAnnotation(JavaConverter.Adapter converterAdapter) { JavaResourcePersistentAttribute resourceAttribute = this.getResourcePersistentAttribute(); for (JavaConverter.Adapter adapter : this.getConverterAdapters()) { if (adapter != converterAdapter) { adapter.removeConverterAnnotation(resourceAttribute); } } } protected JavaConverter buildConverter() { JpaFactory jpaFactory = this.getJpaFactory(); for (JavaConverter.Adapter adapter : this.getConverterAdapters()) { JavaConverter javaConverter = adapter.buildConverter(this, jpaFactory); if (javaConverter != null) { return javaConverter; } } return this.buildNullConverter(); } protected void syncConverter() { Association assoc = this.getConverterAnnotation(); if (assoc == null) { if (this.converter.getType() != null) { this.setConverter_(this.buildNullConverter()); } } else { JavaConverter.Adapter adapter = assoc.getKey(); Annotation annotation = assoc.getValue(); if ((this.converter.getType() == adapter.getConverterType()) && (this.converter.getConverterAnnotation() == annotation)) { this.converter.synchronizeWithResourceModel(); } else { this.setConverter_(adapter.buildConverter(annotation, this, this.getJpaFactory())); } } } /** * Return the first converter annotation we find along with its corresponding * adapter. Return null if there are no converter annotations. */ protected Association getConverterAnnotation() { JavaResourcePersistentAttribute resourceAttribute = this.getResourcePersistentAttribute(); for (JavaConverter.Adapter adapter : this.getConverterAdapters()) { Annotation annotation = adapter.getConverterAnnotation(resourceAttribute); if (annotation != null) { return new SimpleAssociation(adapter, annotation); } } return null; } protected JavaConverter buildNullConverter() { return new NullJavaConverter(this); } // ********** converter adapters ********** /** * Return the converter adapter for the specified converter type. */ protected JavaConverter.Adapter getConverterAdapter(Class converterType) { for (JavaConverter.Adapter adapter : this.getConverterAdapters()) { if (adapter.getConverterType() == converterType) { return adapter; } } return null; } protected Iterable getConverterAdapters() { return CONVERTER_ADAPTERS; } // ********** misc ********** public String getKey() { return MappingKeys.BASIC_ATTRIBUTE_MAPPING_KEY; } @Override protected String getAnnotationName() { return BasicAnnotation.ANNOTATION_NAME; } @Override public boolean isOverridableAttributeMapping() { return true; } // ********** JavaColumn.Owner implementation ********** public ColumnAnnotation getColumnAnnotation() { return (ColumnAnnotation) this.getResourcePersistentAttribute().getNonNullAnnotation(ColumnAnnotation.ANNOTATION_NAME); } public void removeColumnAnnotation() { this.getResourcePersistentAttribute().removeAnnotation(ColumnAnnotation.ANNOTATION_NAME); } public String getDefaultColumnName() { return this.getName(); } public String getDefaultTableName() { return this.getTypeMapping().getPrimaryTableName(); } public boolean tableNameIsInvalid(String tableName) { return this.getTypeMapping().tableNameIsInvalid(tableName); } public Iterator candidateTableNames() { return this.getTypeMapping().allAssociatedTableNames(); } public JptValidator buildColumnValidator(NamedColumn column, NamedColumnTextRangeResolver textRangeResolver) { return new NamedColumnValidator((BaseColumn) column, (BaseColumnTextRangeResolver) textRangeResolver, new EntityTableDescriptionProvider()); } // ********** Java completion proposals ********** @Override public Iterator javaCompletionProposals(int pos, Filter filter, CompilationUnit astRoot) { Iterator result = super.javaCompletionProposals(pos, filter, astRoot); if (result != null) { return result; } result = this.column.javaCompletionProposals(pos, filter, astRoot); if (result != null) { return result; } result = this.converter.javaCompletionProposals(pos, filter, astRoot); if (result != null) { return result; } return null; } // ********** validation ********** @Override public void validate(List messages, IReporter reporter, CompilationUnit astRoot) { super.validate(messages, reporter, astRoot); this.column.validate(messages, reporter, astRoot); this.converter.validate(messages, reporter, astRoot); } }