oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataProject Maven / Gradle / Ivy
The newest version!
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* // Copyright (c) 1998, 2007, Oracle. All rights reserved.
*
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package oracle.toplink.essentials.internal.ejb.cmp3.metadata;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.spi.PersistenceUnitInfo;
import oracle.toplink.essentials.sequencing.Sequence;
import oracle.toplink.essentials.sequencing.TableSequence;
import oracle.toplink.essentials.sequencing.NativeSequence;
import oracle.toplink.essentials.sessions.Project;
import oracle.toplink.essentials.sessions.DatasourceLogin;
import oracle.toplink.essentials.descriptors.ClassDescriptor;
import oracle.toplink.essentials.exceptions.ValidationException;
import oracle.toplink.essentials.queryframework.EJBQLPlaceHolderQuery;
import oracle.toplink.essentials.internal.helper.DatabaseTable;
import oracle.toplink.essentials.internal.sessions.AbstractSession;
import oracle.toplink.essentials.internal.ejb.cmp3.EJBQueryImpl;
import oracle.toplink.essentials.internal.ejb.cmp3.base.QueryHintsHandler;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.MetadataAccessor;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.RelationshipAccessor;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.queries.MetadataQueryHint;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.queries.MetadataNamedQuery;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.queries.MetadataNamedNativeQuery;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.sequencing.MetadataGeneratedValue;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.sequencing.MetadataTableGenerator;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.sequencing.MetadataSequenceGenerator;
import oracle.toplink.essentials.internal.ejb.cmp3.xml.XMLHelper;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Document;
/**
* @author Guy Pelletier
* @since TopLink EJB 3.0 Reference Implementation
*/
public class MetadataProject {
// persistence unit that is represented by this project
protected PersistenceUnitInfo m_PUInfo;
// Names of all the 'weavable' classes for this project.
protected Collection m_weavableClassNames = new HashSet();
// URL to Document object map of all the mapping files for this PU.
// The reason for using URL instead of name is that name is not unique.
protected Map m_mappingFiles = new HashMap();
// The session we are currently processing for.
protected AbstractSession m_session;
// Boolean to specify if we should weave for value holders.
protected boolean m_enableLazyForOneToOne;
// Persistence unit metadata for this project.
protected MetadataPersistenceUnit m_persistenceUnit;
// List of mapped-superclasses found in XML for this project/persistence unit.
protected HashMap m_mappedSuperclassNodes;
protected HashMap m_mappedSuperclasses;
// List of embeddables found in XML for this project/persistence unit.
protected HashMap m_embeddableNodes;
protected HashMap m_embeddables;
// All the descriptors for this project.
protected HashMap m_allDescriptors;
// Descriptors that have relationships.
protected HashSet m_descriptorsWithRelationships;
// Named queries for this project.
protected HashMap m_namedQueries;
// NamedNativeQueries for this project.
protected HashMap m_namedNativeQueries;
// Sequencing metadata.
protected HashMap m_generatedValues;
protected HashMap m_tableGenerators;
protected HashMap m_sequenceGenerators;
// Default listeners that need to be applied to each entity in the
// persistence unit (unless they exclude them).
protected HashMap m_defaultListeners;
/**
* INTERNAL:
*/
public MetadataProject(PersistenceUnitInfo puInfo, AbstractSession session, boolean enableLazyForOneToOne) {
m_PUInfo = puInfo;
m_session = session;
m_enableLazyForOneToOne = enableLazyForOneToOne;
m_defaultListeners = new HashMap();
m_namedQueries = new HashMap();
m_namedNativeQueries = new HashMap();
m_mappedSuperclassNodes = new HashMap();
m_mappedSuperclasses = new HashMap();
m_embeddableNodes = new HashMap();
m_embeddables = new HashMap();
m_allDescriptors = new HashMap();
m_descriptorsWithRelationships = new HashSet();
m_generatedValues = new HashMap();
m_tableGenerators = new HashMap();
m_sequenceGenerators = new HashMap();
}
/**
* INTERNAL:
*/
public void addDefaultListeners(NodeList nodes, XMLHelper helper) {
m_defaultListeners.put(helper, nodes);
}
/**
* INTERNAL:
* This method will add the descriptor to the actual TopLink project as
* well if it has not already been added.
*/
public void addDescriptor(MetadataDescriptor descriptor) {
// Set the persistence unit defaults (if there are any) on the descriptor.
if (m_persistenceUnit != null) {
descriptor.setAccess(m_persistenceUnit.getAccess());
descriptor.setSchema(m_persistenceUnit.getSchema());
descriptor.setCatalog(m_persistenceUnit.getCatalog());
descriptor.setIsCascadePersist(m_persistenceUnit.isCascadePersist());
descriptor.setIgnoreAnnotations(m_persistenceUnit.isMetadataComplete());
}
Project project = getSession().getProject();
ClassDescriptor descriptorOnProject = MetadataHelper.findDescriptor(project, descriptor.getJavaClass());
if (descriptorOnProject == null) {
project.addDescriptor(descriptor.getClassDescriptor());
} else {
descriptor.setDescriptor(descriptorOnProject);
}
m_allDescriptors.put(descriptor.getJavaClassName(), descriptor);
}
/**
* INTERNAL:
*/
public void addGeneratedValue(MetadataGeneratedValue metadatageneratedvalue, Class entityClass) {
m_generatedValues.put(entityClass, metadatageneratedvalue);
}
/**
* INTERNAL:
* Add a mapped-superclass that we found in an XML document.
*/
public void addMappedSuperclass(Class mappedSuperclass, Node node, XMLHelper helper) {
m_mappedSuperclasses.put(mappedSuperclass.getName(), helper);
m_mappedSuperclassNodes.put(mappedSuperclass.getName(), node);
}
/**
* INTERNAL:
* Add an embeddable that we found in an XML document.
*/
public void addEmbeddable(Class embeddable, Node node, XMLHelper helper) {
m_embeddables.put(embeddable.getName(), helper);
m_embeddableNodes.put(embeddable.getName(), node);
}
/**
* INTERNAL:
*/
public void addNamedNativeQuery(MetadataNamedNativeQuery namedNativeQuery) {
m_namedNativeQueries.put(namedNativeQuery.getName(), namedNativeQuery);
}
/**
* INTERNAL:
*/
public void addNamedQuery(MetadataNamedQuery namedQuery) {
m_namedQueries.put(namedQuery.getName(), namedQuery);
}
/**
* INTERNAL:
*/
public void addRelationshipDescriptor(MetadataDescriptor descriptor) {
m_descriptorsWithRelationships.add(descriptor);
}
/**
* INTERNAL:
*/
public void addSequenceGenerator(MetadataSequenceGenerator sequenceGenerator) {
m_sequenceGenerators.put(sequenceGenerator.getName(), sequenceGenerator);
}
/**
* INTERNAL:
*/
public void addTableGenerator(MetadataTableGenerator tableGenerator) {
m_tableGenerators.put(tableGenerator.getName(), tableGenerator);
}
/**
* INTERNAL:
* This method frees up resources acquired by this object.
*/
public void cleanup() {
// get rid of the DOM trees.
m_mappingFiles.clear();
}
/**
* INTERNAL:
*/
public boolean containsDescriptor(Class cls) {
return m_allDescriptors.containsKey(cls.getName());
}
/**
* INTERNAL:
*/
public boolean enableLazyForOneToOne() {
return m_enableLazyForOneToOne;
}
/**
* INTERNAL:
*/
public HashMap getDefaultListeners() {
return m_defaultListeners;
}
/**
* INTERNAL:
*/
public MetadataDescriptor getDescriptor(Class cls) {
if (cls == null) {
return null;
} else {
MetadataDescriptor descriptor = m_allDescriptors.get(cls.getName());
if (descriptor == null) {
throw ValidationException.classNotListedInPersistenceUnit(cls.getName());
} else {
return descriptor;
}
}
}
/**
* INTERNAL:
*/
public Collection getDescriptors() {
return m_allDescriptors.values();
}
/**
* INTERNAL:
*/
public XMLHelper getMappedSuperclassHelper(Class cls) {
return m_mappedSuperclasses.get(cls.getName());
}
/**
* INTERNAL:
*/
public Node getMappedSuperclassNode(Class cls) {
return m_mappedSuperclassNodes.get(cls.getName());
}
/**
* INTERNAL:
*/
public Map getMappingFiles() {
return Collections.unmodifiableMap(m_mappingFiles);
}
/**
* INTERNAL:
*/
public XMLHelper getEmbeddableHelper(Class cls) {
return m_embeddables.get(cls.getName());
}
/**
* INTERNAL:
*/
public Node getEmbeddableNode(Class cls) {
return m_embeddableNodes.get(cls.getName());
}
/**
* INTERNAL:
*/
public MetadataNamedNativeQuery getNamedNativeQuery(String name) {
return m_namedNativeQueries.get(name);
}
/**
* INTERNAL:
*/
public MetadataNamedQuery getNamedQuery(String name) {
return m_namedQueries.get(name);
}
/**
* INTERNAL:
* Set the classes for processing.
*/
public MetadataPersistenceUnit getPersistenceUnit() {
return m_persistenceUnit;
}
/**
* INTERNAL:
*/
public PersistenceUnitInfo getPUInfo() {
return m_PUInfo;
}
/**
* INTERNAL:
*/
public HashSet getRelationshipDescriptors() {
return m_descriptorsWithRelationships;
}
/**
* INTERNAL:
*/
public MetadataSequenceGenerator getSequenceGenerator(String name) {
return m_sequenceGenerators.get(name);
}
/**
* INTERNAL:
*/
public Collection getSequenceGenerators() {
return m_sequenceGenerators.values();
}
/**
* INTERNAL:
*/
public AbstractSession getSession() {
return m_session;
}
/**
* INTERNAL:
*/
public MetadataTableGenerator getTableGenerator(String name) {
return m_tableGenerators.get(name);
}
/**
* INTERNAL:
*/
public Collection getTableGenerators() {
return m_tableGenerators.values();
}
/**
* INTERNAL:
* Returns all those classes in this project that are available for
* weaving. This list currently includes entity and embeddables classes.
*/
public Collection getWeavableClassNames() {
return Collections.unmodifiableCollection(m_weavableClassNames);
}
/**
* INTERNAL:
*/
public boolean hasConflictingSequenceGenerator(MetadataSequenceGenerator sequenceGenerator) {
if (hasSequenceGenerator(sequenceGenerator.getName())) {
return ! getSequenceGenerator(sequenceGenerator.getName()).equals(sequenceGenerator);
} else {
return false;
}
}
/**
* INTERNAL:
*/
public boolean hasConflictingTableGenerator(MetadataTableGenerator tableGenerator) {
if (hasTableGenerator(tableGenerator.getName())) {
return ! getTableGenerator(tableGenerator.getName()).equals(tableGenerator);
} else {
return false;
}
}
/**
* INTERNAL:
*/
public boolean hasDescriptors() {
return ! m_allDescriptors.isEmpty();
}
/**
* INTERNAL:
*/
public boolean hasMappedSuperclass(Class cls) {
return m_mappedSuperclasses.containsKey(cls.getName());
}
/**
* INTERNAL:
*/
public boolean hasEmbeddable(Class cls) {
return m_embeddables.containsKey(cls.getName());
}
/**
* INTERNAL:
*/
public boolean hasNamedNativeQuery(String name) {
return m_namedNativeQueries.containsKey(name);
}
/**
* INTERNAL:
*/
public boolean hasNamedQuery(String name) {
return m_namedQueries.containsKey(name);
}
/**
* INTERNAL:
* Set the classes for processing.
*/
public boolean hasPersistenceUnit() {
return m_persistenceUnit != null;
}
/**
* INTERNAL:
*/
public boolean hasSequenceGenerator(String name) {
return getSequenceGenerator(name) != null;
}
/**
* INTERNAL:
*/
public boolean hasTableGenerator(String name) {
return getTableGenerator(name) != null;
}
/**
* INTERNAL:
*
* Stage 2 processing. That is, it does all the extra processing that
* couldn't be completed in the original metadata accessor processing.
*/
public void process() {
processSequencing();
processRelationshipDescriptors();
}
/**
* INTERNAL:
* Process the named native queries we found and add them to the given
* session.
*/
public void processNamedNativeQueries(ClassLoader loader) {
for (MetadataNamedNativeQuery query : m_namedNativeQueries.values()) {
HashMap hints = processQueryHints(query.getHints(), query.getName());
Class resultClass = query.getResultClass();
if (resultClass != void.class) {
resultClass = MetadataHelper.getClassForName(resultClass.getName(), loader);
m_session.addQuery(query.getName(), EJBQueryImpl.buildSQLDatabaseQuery(resultClass, query.getEJBQLString(), hints));
} else {
String resultSetMapping = query.getResultSetMapping();
if (! resultSetMapping.equals("")) {
m_session.addQuery(query.getName(), EJBQueryImpl.buildSQLDatabaseQuery(resultSetMapping, query.getEJBQLString(), hints));
} else {
// Neither a resultClass or resultSetMapping is specified so place in a temp query on the session
m_session.addQuery(query.getName(), EJBQueryImpl.buildSQLDatabaseQuery(query.getEJBQLString(), hints));
}
}
}
}
/**
* INTERNAL:
* Process the named queries we found and add them to the given session.
*/
public void processNamedQueries(MetadataValidator validator) {
for (MetadataNamedQuery query : m_namedQueries.values()) {
try {
HashMap hints = processQueryHints(query.getHints(), query.getName());
m_session.addEjbqlPlaceHolderQuery(new EJBQLPlaceHolderQuery(query.getName(), query.getEJBQLString(), hints));
} catch (Exception exception) {
validator.throwErrorProcessingNamedQueryAnnotation(query.getClass(), query.getName(), exception);
}
}
}
/**
* INTERNAL:
* Process a list of MetadataQueryHint.
*/
protected HashMap processQueryHints(List hints, String queryName) {
HashMap hm = new HashMap();
for (MetadataQueryHint hint : hints) {
QueryHintsHandler.verify(hint.getName(), hint.getValue(), queryName, m_session);
hm.put(hint.getName(), hint.getValue());
}
return hm;
}
/**
* INTERNAL:
* Process the related descriptors.
*/
protected void processRelationshipDescriptors() {
for (MetadataDescriptor descriptor : (HashSet) getRelationshipDescriptors()) {
for (RelationshipAccessor accessor : (Collection) descriptor.getRelationshipAccessors()) {
accessor.processRelationship();
}
}
}
/**
* INTERNAL:
* Process the sequencing information.
*/
protected void processSequencing() {
if (! m_generatedValues.isEmpty()) {
DatasourceLogin login = m_session.getProject().getLogin();
// Generators referenced from Id should have correct type
for (MetadataGeneratedValue generatedValue : m_generatedValues.values()) {
String type = generatedValue.getStrategy();
String generatorName = generatedValue.getGenerator();
if (type.equals(MetadataConstants.TABLE)) {
MetadataSequenceGenerator sequenceGenerator = m_sequenceGenerators.get(generatorName);
if (sequenceGenerator != null) {
// WIP
}
} else if (type.equals(MetadataConstants.SEQUENCE) || type.equals(MetadataConstants.IDENTITY)) {
MetadataTableGenerator tableGenerator = m_tableGenerators.get(generatorName);
if (tableGenerator != null) {
// WIP
}
}
}
Sequence defaultAutoSequence = null;
TableSequence defaultTableSequence = new TableSequence(MetadataConstants.DEFAULT_TABLE_GENERATOR);
NativeSequence defaultObjectNativeSequence = new NativeSequence(MetadataConstants.DEFAULT_SEQUENCE_GENERATOR, false);
NativeSequence defaultIdentityNativeSequence = new NativeSequence(MetadataConstants.DEFAULT_IDENTITY_GENERATOR, 1, true);
// Sequences keyed on generator names.
Hashtable sequences = new Hashtable();
for (MetadataSequenceGenerator sequenceGenerator : m_sequenceGenerators.values()) {
String sequenceGeneratorName = sequenceGenerator.getName();
String seqName = (sequenceGenerator.getSequenceName().equals("")) ? sequenceGeneratorName : sequenceGenerator.getSequenceName();
NativeSequence sequence = new NativeSequence(seqName, sequenceGenerator.getAllocationSize(), false);
sequences.put(sequenceGeneratorName, sequence);
if (sequenceGeneratorName.equals(MetadataConstants.DEFAULT_AUTO_GENERATOR)) {
// SequenceGenerator defined with DEFAULT_AUTO_GENERATOR.
// The sequence it defines will be used as a defaultSequence.
defaultAutoSequence = sequence;
} else if (sequenceGeneratorName.equals(MetadataConstants.DEFAULT_SEQUENCE_GENERATOR)) {
// SequenceGenerator deinfed with DEFAULT_SEQUENCE_GENERATOR.
// All sequences of GeneratorType SEQUENCE
// referencing non-defined generators will use a clone of
// the sequence defined by this generator.
defaultObjectNativeSequence = sequence;
}
}
for (MetadataTableGenerator tableGenerator : m_tableGenerators.values()) {
String tableGeneratorName = tableGenerator.getName();
String seqName = (tableGenerator.getPkColumnValue().equals("")) ? tableGeneratorName : tableGenerator.getPkColumnValue();
TableSequence sequence = new TableSequence(seqName, tableGenerator.getAllocationSize(), tableGenerator.getInitialValue());
sequences.put(tableGeneratorName, sequence);
//bug 2647: pull schema and catalog defaults from the persistence Unit if they are not defined.
String catalogName = tableGenerator.getCatalog();
String schemaName = tableGenerator.getSchema();
if (this.getPersistenceUnit()!=null){
catalogName = catalogName.length()>0? catalogName: this.getPersistenceUnit().getCatalog();
schemaName = schemaName.length()>0? schemaName: this.getPersistenceUnit().getSchema();
}
// Get the database table from the @TableGenerator values.
// In case tableGenerator.table().equals("") default sequence
// table name will be extracted from sequence and used, see
// TableSequence class.
sequence.setTable(new DatabaseTable(MetadataHelper.getFullyQualifiedTableName(tableGenerator.getTable(), sequence.getTableName(), catalogName, schemaName)));
// Process the @UniqueConstraints for this table.
for (String[] uniqueConstraint : tableGenerator.getUniqueConstraints()) {
sequence.getTable().addUniqueConstraints(uniqueConstraint);
}
if (! tableGenerator.getPkColumnName().equals("")) {
sequence.setNameFieldName(tableGenerator.getPkColumnName());
}
if (! tableGenerator.getValueColumnName().equals("")) {
sequence.setCounterFieldName(tableGenerator.getValueColumnName());
}
if (tableGeneratorName.equals(MetadataConstants.DEFAULT_AUTO_GENERATOR)) {
// TableGenerator defined with DEFAULT_AUTO_GENERATOR.
// The sequence it defines will be used as a defaultSequence.
defaultAutoSequence = sequence;
} else if (tableGeneratorName.equals(MetadataConstants.DEFAULT_TABLE_GENERATOR)) {
// SequenceGenerator defined with DEFAULT_TABLE_GENERATOR.
// All sequences of GenerationType TABLE referencing non-
// defined generators will use a clone of the sequence
// defined by this generator.
defaultTableSequence = sequence;
}
}
// Finally loop through descriptors and set sequences as required into
// Descriptors and Login
boolean usesAuto = false;
for (Class entityClass : m_generatedValues.keySet()) {
MetadataDescriptor descriptor = m_allDescriptors.get(entityClass.getName());
MetadataGeneratedValue generatedValue = m_generatedValues.get(entityClass);
String generatorName = generatedValue.getGenerator();
Sequence sequence = null;
if (! generatorName.equals("")) {
sequence = sequences.get(generatorName);
}
if (sequence == null) {
if (generatedValue.getStrategy().equals(MetadataConstants.TABLE)) {
if (generatorName.equals("")) {
sequence = defaultTableSequence;
} else {
sequence = (Sequence)defaultTableSequence.clone();
sequence.setName(generatorName);
}
} else if (generatedValue.getStrategy().equals(MetadataConstants.SEQUENCE)) {
if (generatorName.equals("")) {
sequence = defaultObjectNativeSequence;
} else {
sequence = (Sequence)defaultObjectNativeSequence.clone();
sequence.setName(generatorName);
}
} else if (generatedValue.getStrategy().equals(MetadataConstants.IDENTITY)) {
if (generatorName.equals("")) {
sequence = defaultIdentityNativeSequence;
} else {
sequence = (Sequence)defaultIdentityNativeSequence.clone();
sequence.setName(generatorName);
}
}
}
if (sequence != null) {
descriptor.setSequenceNumberName(sequence.getName());
login.addSequence(sequence);
} else {
// this must be generatedValue.getStrategy().equals(MetadataConstants.AUTO)
usesAuto = true;
String seqName;
if (generatorName.equals("")) {
if (defaultAutoSequence != null) {
seqName = defaultAutoSequence.getName();
} else {
seqName = MetadataConstants.DEFAULT_AUTO_GENERATOR;
}
} else {
seqName = generatorName;
}
descriptor.setSequenceNumberName(seqName);
}
}
if(usesAuto) {
if (defaultAutoSequence != null) {
login.setDefaultSequence(defaultAutoSequence);
}
}
}
}
/**
* INTERNAL:
*/
public void setMappingFiles(Map mappingFiles) {
m_mappingFiles.clear();
m_mappingFiles.putAll(mappingFiles);
}
/**
* INTERNAL:
* Set the classes for processing.
*/
public void setPersistenceUnit(MetadataPersistenceUnit persistenceUnit) {
m_persistenceUnit = persistenceUnit;
}
/**
* INTERNAL:
*/
public void setWeavableClassNames(Collection weavableClassNames) {
m_weavableClassNames.clear();
m_weavableClassNames.addAll(weavableClassNames);
}
}