Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the "License"). You may not use this file except
* in compliance with the License.
*
* You can obtain a copy of the license at
* glassfish/bootstrap/legal/CDDLv1.0.txt or
* https://glassfish.dev.java.net/public/CDDLv1.0.html.
* See the License for the specific language governing
* permissions and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* HEADER in each file and include the License file at
* glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
* add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your
* own identifying information: Portions Copyright [yyyy]
* [name of copyright owner]
*/
// Copyright (c) 1998, 2007, Oracle. All rights reserved.
package oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.lang.annotation.Annotation;
import java.lang.Boolean;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Type;
import javax.persistence.Column;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.PrimaryKeyJoinColumns;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.ClassAccessor;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.objects.MetadataAccessibleObject;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.objects.MetadataClass;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.objects.MetadataMethod;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.columns.MetadataPrimaryKeyJoinColumn;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.columns.MetadataPrimaryKeyJoinColumns;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.tables.MetadataTable;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataHelper;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataLogger;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataProject;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataValidator;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataConstants;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataProcessor;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataDescriptor;
import oracle.toplink.essentials.internal.helper.ClassConstants;
import oracle.toplink.essentials.internal.helper.DatabaseField;
import oracle.toplink.essentials.internal.helper.Helper;
import oracle.toplink.essentials.internal.queryframework.CollectionContainerPolicy;
import oracle.toplink.essentials.mappings.CollectionMapping;
import oracle.toplink.essentials.mappings.DatabaseMapping;
/**
* Top level metatata accessor.
*
* @author Guy Pelletier
* @since TopLink EJB 3.0 Reference Implementation
*/
public abstract class MetadataAccessor {
private boolean m_isProcessed;
private Boolean m_isRelationship;
protected MetadataLogger m_logger;
protected MetadataProject m_project;
protected MetadataProcessor m_processor;
protected MetadataValidator m_validator;
protected MetadataDescriptor m_descriptor;
protected MetadataAccessibleObject m_accessibleObject;
/**
* INTERNAL:
*/
public MetadataAccessor(MetadataAccessibleObject accessibleObject, ClassAccessor classAccessor) {
this(accessibleObject, classAccessor.getProcessor(), classAccessor.getDescriptor());
}
/**
* INTERNAL:
*/
public MetadataAccessor(MetadataAccessibleObject accessibleObject, MetadataProcessor processor, MetadataDescriptor descriptor) {
m_isProcessed = false;
m_processor = processor;
m_descriptor = descriptor;
m_logger = processor.getLogger();
m_project = processor.getProject();
m_validator = processor.getValidator();
m_accessibleObject = accessibleObject;
}
/**
* INTERNAL:
* Return the annotated element for this accessor.
*/
public AnnotatedElement getAnnotatedElement() {
return m_accessibleObject.getAnnotatedElement();
}
/**
* INTERNAL:
* Return the annotated element for this accessor.
*/
protected T getAnnotation(Class annotation) {
return (T) getAnnotation(annotation, getAnnotatedElement());
}
/**
* INTERNAL:
* Return the annotated element for this accessor.
*/
protected T getAnnotation(Class annotation, AnnotatedElement annotatedElement) {
return (T) MetadataHelper.getAnnotation(annotation, annotatedElement, m_descriptor);
}
/**
* INTERNAL:
* Return the attribute name for this accessor.
*/
public String getAttributeName() {
return m_accessibleObject.getAttributeName();
}
/**
* INTERNAL:
* Return the MetadataDescriptor for this accessor.
*/
public MetadataDescriptor getDescriptor() {
return m_descriptor;
}
/**
* INTERNAL:
*
* Subclasses that support processing a fetch type should override this
* method, otherwise a runtime development exception is thrown for those
* accessors who call this method and don't implement it themselves.
*/
public String getFetchType() {
throw new RuntimeException("Development exception. The accessor: [" + this + "] should not call the getFetchType method unless it overrides it.");
}
/**
* INTERNAL: (Overridden in ClassAccessor)
* Return the java class associated with this accessor's descriptor.
*/
public Class getJavaClass() {
return m_descriptor.getJavaClass();
}
/**
* INTERNAL:
* Return the java class that defines this accessor.
*/
protected String getJavaClassName() {
return getJavaClass().getName();
}
/**
* INTERNAL:
* Return the metadata validator.
*/
public MetadataLogger getLogger() {
return m_logger;
}
/**
* INTERNAL:
* Return the map key class from a generic Map type. If it is not generic,
* then null is returned.
*/
protected Class getMapKeyClass() {
return m_accessibleObject.getMapKeyClass();
}
/**
* INTERNAL:
* Returns the name of this accessor. If it is a field, it will return
* the field name. For a method it will return the method name.
*/
public String getName() {
return m_accessibleObject.getName();
}
/**
* INTERNAL:
* Helper method to return a field name from a candidate field name and a
* default field name.
*
* Requires the context from where this method is called to output the
* correct logging message when defaulting the field name.
*/
protected String getName(DatabaseField field, String defaultName, String context) {
return getName(field.getName(), defaultName, context);
}
/**
* INTERNAL:
* Helper method to return a field name from a candidate field name and a
* default field name.
*
* Requires the context from where this method is called to output the
* correct logging message when defaulting the field name.
*
* In some cases, both the name and defaultName could be "" or null,
* therefore, don't log any message and return name.
*/
protected String getName(String name, String defaultName, String context) {
// Check if a candidate was specified otherwise use the default.
if (name != null && !name.equals("")) {
return name;
} else if (defaultName == null || defaultName.equals("")) {
return "";
} else {
// Log the defaulting field name based on the given context.
m_logger.logConfigMessage(context, getAnnotatedElement(), defaultName);
return defaultName;
}
}
/**
* INTERNAL: (Overridden in XMLClassAccessor and XMLOneToOneAccessor)
* Process the @PrimaryKeyJoinColumns and @PrimaryKeyJoinColumn.
*/
protected MetadataPrimaryKeyJoinColumns getPrimaryKeyJoinColumns(String sourceTableName, String targetTableName) {
PrimaryKeyJoinColumn primaryKeyJoinColumn = getAnnotation(PrimaryKeyJoinColumn.class);
PrimaryKeyJoinColumns primaryKeyJoinColumns = getAnnotation(PrimaryKeyJoinColumns.class);
return new MetadataPrimaryKeyJoinColumns(primaryKeyJoinColumns, primaryKeyJoinColumn, sourceTableName, targetTableName);
}
/**
* INTERNAL:
* Return the MetadataProject.
*/
public MetadataProject getProject() {
return m_project;
}
/**
* INTERNAL:
* Return the MetadataProcessor.
*/
public MetadataProcessor getProcessor() {
return m_processor;
}
/**
* INTERNAL:
* Return the raw class for this accessor.
* Eg. For an accessor with a type of java.util.Collection, this
* method will return java.util.Collection
*/
public Class getRawClass() {
return m_accessibleObject.getRawClass();
}
/**
* INTERNAL: (Overridden in RelationshipAccessor)
*
* Return the reference class for this accessor. By default the reference
* class is the raw class. Some accessors, namely relationship accessors,
* will need to override this behavior to extract a reference class from
* generics.
*/
public Class getReferenceClass() {
return m_accessibleObject.getRawClass();
}
/**
* INTERNAL:
*
* Return the reference class name for this accessor.
*/
public String getReferenceClassName() {
return getReferenceClass().getName();
}
/**
* INTERNAL:
* Return the reference metadata descriptor for this accessor.
*/
public MetadataDescriptor getReferenceDescriptor() {
return m_project.getDescriptor(getReferenceClass());
}
/**
* INTERNAL:
* Return the relation type of this accessor.
*/
protected Type getRelationType() {
return m_accessibleObject.getRelationType();
}
/**
* INTERNAL:
* Returns the set method name of a method accessor. Note, this method
* should not be called when processing field access.
*/
protected String getSetMethodName() {
return ((MetadataMethod) m_accessibleObject).getSetMethodName();
}
/**
* INTERNAL:
* Return the upper cased attribute name for this accessor. Used when
* defaulting.
*/
protected String getUpperCaseAttributeName() {
return getAttributeName().toUpperCase();
}
/**
* INTERNAL:
* Return the upper case java class that defines this accessor.
*/
protected String getUpperCaseShortJavaClassName() {
return Helper.getShortClassName(getJavaClassName()).toUpperCase();
}
/**
* INTERNAL:
* Return the metadata validator.
*/
public MetadataValidator getValidator() {
return m_validator;
}
/**
* INTERNAL:
* Method to check if an annotated element has a @Column.
*/
protected boolean hasColumn() {
return isAnnotationPresent(Column.class);
}
/**
* INTERNAL:
*
* Method to check if this accessor has @PrimaryKeyJoinColumns.
*/
protected boolean hasPrimaryKeyJoinColumns() {
return isAnnotationPresent(PrimaryKeyJoinColumns.class);
}
/**
* INTERNAL:
* Indicates whether the specified annotation is present on the annotated
* element for this accessor. Method checks against the metadata complete
* flag.
*/
protected boolean isAnnotationPresent(Class annotation) {
return isAnnotationPresent(annotation, getAnnotatedElement());
}
/**
* INTERNAL:
* Indicates whether the specified annotation is present on the annotated
* element for this accessor. Method checks against the metadata complete
* flag.
*/
protected boolean isAnnotationPresent(Class annotation, AnnotatedElement annotatedElement) {
return MetadataHelper.isAnnotationPresent(annotation, annotatedElement, m_descriptor);
}
/**
* INTERNAL:
* Return true if this accessor represents a basic mapping.
*/
public boolean isBasic() {
return false;
}
/**
* INTERNAL:
* Return true if this accessor represents a class.
*/
public boolean isClass() {
return false;
}
/**
* INTERNAL:
* Return true if this accessor represents an aggregate mapping.
*/
public boolean isEmbedded() {
return false;
}
/**
* INTERNAL:
* Return true if this accessor represents an aggregate id mapping.
*/
public boolean isEmbeddedId() {
return false;
}
/**
* INTERNAL:
* Return true if this accessor represents a m-m relationship.
*/
public boolean isManyToMany() {
return false;
}
/**
* INTERNAL:
* Return true if this accessor represents a m-1 relationship.
*/
public boolean isManyToOne() {
return false;
}
/**
* INTERNAL:
* Return true if this accessor represents a 1-m relationship.
*/
public boolean isOneToMany() {
return false;
}
/**
* INTERNAL:
* Return true if this accessor represents a 1-1 relationship.
*/
public boolean isOneToOne() {
return false;
}
/**
* INTERNAL:
*
* Subclasses that support processing an optional setting should override
* this method, otherwise a runtime development exception is thrown for
* those accessors who call this method and don't implement it themselves.
*/
public boolean isOptional() {
throw new RuntimeException("Development exception. The accessor: [" + this + "] should not call the isOptional method unless it overrides it.");
}
/**
* INTERNAL:
* Return true if this accessor method represents a relationship. It will
* cache the boolean value to avoid multiple checks and validation.
*/
public boolean isRelationship() {
if (m_isRelationship == null) {
m_isRelationship = new Boolean(isManyToOne() || isManyToMany() || isOneToMany() || isOneToOne());
}
return m_isRelationship.booleanValue();
}
/**
* INTERNAL:
* Return true if this is an XML processing accessor.
*/
public boolean isXMLAccessor() {
return false;
}
/**
* INTERNAL:
* Return true if this accessor has already been processed.
*/
public boolean isProcessed() {
return m_isProcessed;
}
/**
* INTERNAL:
* Every accessor knows how to process themselves since they have all the
* information they need.
*/
public abstract void process();
/**
* INTERNAL: (Overidden in XMLClassAccessor and XMLEmbeddedAccessor)
* Fast track processing a ClassAccessor for the given descriptor.
* Inheritance root classes and embeddables may be fast tracked.
*/
protected ClassAccessor processAccessor(MetadataDescriptor descriptor) {
ClassAccessor accessor = new ClassAccessor(new MetadataClass(descriptor.getJavaClass()), getProcessor(), descriptor);
descriptor.setClassAccessor(accessor);
accessor.process();
return accessor;
}
/**
* INTERNAL:
*
* Process the primary key join columms for this accessors annotated element.
*/
protected List processPrimaryKeyJoinColumns(MetadataPrimaryKeyJoinColumns primaryKeyJoinColumns) {
// This call will add any defaulted columns as necessary.
List pkJoinColumns = primaryKeyJoinColumns.values(m_descriptor);
if (m_descriptor.hasCompositePrimaryKey()) {
// Validate the number of primary key fields defined.
if (pkJoinColumns.size() != m_descriptor.getPrimaryKeyFields().size()) {
m_validator.throwIncompletePrimaryKeyJoinColumnsSpecified(getJavaClass(), getAnnotatedElement());
}
// All the primary and foreign key field names should be specified.
for (MetadataPrimaryKeyJoinColumn pkJoinColumn : pkJoinColumns) {
if (pkJoinColumn.isPrimaryKeyFieldNotSpecified() || pkJoinColumn.isForeignKeyFieldNotSpecified()) {
m_validator.throwIncompletePrimaryKeyJoinColumnsSpecified(getJavaClass(), getAnnotatedElement());
}
}
} else {
if (pkJoinColumns.size() > 1) {
m_validator.throwExcessivePrimaryKeyJoinColumnsSpecified(getJavaClass(), getAnnotatedElement());
}
}
return pkJoinColumns;
}
/**
* INTERNAL:
* Common table processing for table, secondary table, join table and
* collection table.
*/
protected void processTable(MetadataTable table, String defaultName) {
// Name could be "", need to check against the default name.
String name = getName(table.getName(), defaultName, table.getNameContext());
// Catalog could be "", need to check for an XML default.
String catalog = getName(table.getCatalog(), m_descriptor.getCatalog(), table.getCatalogContext());
// Schema could be "", need to check for an XML default.
String schema = getName(table.getSchema(), m_descriptor.getSchema(), table.getSchemaContext());
// Build a fully qualified name and set it on the table.
table.setName(MetadataHelper.getFullyQualifiedTableName(name, catalog, schema));
}
/**
* INTERNAL:
*
* Set the getter and setter access methods for this accessor.
*/
protected void setAccessorMethods(DatabaseMapping mapping) {
if (m_descriptor.usesPropertyAccess()) {
mapping.setGetMethodName(getName());
mapping.setSetMethodName(getSetMethodName());
}
}
/**
* INTERNAL:
* Return the annotated element for this accessor.
*/
public void setAnnotatedElement(AnnotatedElement annotatedElement) {
m_accessibleObject.setAnnotatedElement(annotatedElement);
}
/**
* INTERNAL:
* Set the correct indirection policy on a collection mapping. Method
* assume that the reference class has been set on the mapping before
* calling this method.
*/
protected void setIndirectionPolicy(CollectionMapping mapping, String mapKey) {
Class rawClass = getRawClass();
if (usesIndirection()) {
if (rawClass == Map.class) {
mapping.useTransparentMap(mapKey);
} else if (rawClass == List.class) {
mapping.useTransparentList();
} else if (rawClass == Collection.class) {
mapping.useTransparentCollection();
mapping.setContainerPolicy(new CollectionContainerPolicy(ClassConstants.IndirectList_Class));
} else if (rawClass == Set.class) {
mapping.useTransparentSet();
} else {
// Because of validation we should never get this far.
}
} else {
mapping.dontUseIndirection();
if (rawClass == Map.class) {
mapping.useMapClass(java.util.Hashtable.class, mapKey);
} else if (rawClass == Set.class) {
mapping.useCollectionClass(java.util.HashSet.class);
} else {
mapping.useCollectionClass(java.util.Vector.class);
}
}
}
/**
* INTERNAL:
*/
public void setIsProcessed() {
m_isProcessed = true;
}
/**
* INTERNAL:
*/
public boolean usesIndirection() {
return getFetchType().equals(MetadataConstants.LAZY);
}
}