/*******************************************************************************
* Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/
package org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.relational;
import java.util.Iterator;
import java.util.List;
import org.eclipse.persistence.tools.workbench.mappingsmodel.MWModel;
import org.eclipse.persistence.tools.workbench.mappingsmodel.ProblemConstants;
import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.MWDescriptor;
import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.MWDescriptorInheritancePolicy;
import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.MWMappingDescriptor;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.MWMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWAbstractTableReferenceMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWAggregateMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.relational.MWCollectionMapping;
import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.MWClass;
import org.eclipse.persistence.tools.workbench.mappingsmodel.project.MWProjectDefaultsPolicy;
import org.eclipse.persistence.tools.workbench.mappingsmodel.project.relational.MWRelationalProject;
import org.eclipse.persistence.tools.workbench.utility.iterators.NullIterator;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.RelationalDescriptor;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.mappings.querykeys.DirectQueryKey;
public final class MWAggregateDescriptor extends MWRelationalClassDescriptor
{
// ********** static methods **********
public static XMLDescriptor buildDescriptor() {
XMLDescriptor descriptor = new XMLDescriptor();
descriptor.setJavaClass(MWAggregateDescriptor.class);
descriptor.getInheritancePolicy().setParentClass(MWRelationalClassDescriptor.class);
return descriptor;
}
// ********** constructors **********
/** Default constructor - for TopLink use only */
private MWAggregateDescriptor() {
super();
}
public MWAggregateDescriptor(MWRelationalProject project, MWClass type, String name) {
super(project, type, name);
}
// ********** MWRelationalDescriptor implementation **********
public Iterator associatedTables() {
return NullIterator.instance();
}
public int associatedTablesSize() {
return 0;
}
public void notifyExpressionsToRecalculateQueryables() {
}
// ********** MWMappingDescriptor overrides **********
public void addMapping(MWMapping mapping) {
super.addMapping(mapping);
this.getProject().recalculateAggregatePathsToColumn(this);
}
public void removeMapping(MWMapping mapping) {
super.removeMapping(mapping);
this.getProject().recalculateAggregatePathsToColumn(this);
}
protected void setInheritancePolicy(MWDescriptorInheritancePolicy newValue) {
super.setInheritancePolicy(newValue);
this.getProject().recalculateAggregatePathsToColumn(this);
}
//************** morphing support ***************
public MWAggregateDescriptor asMWAggregateDescriptor() {
return this;
}
public void initializeOn(MWDescriptor newDescriptor) {
((MWRelationalDescriptor) newDescriptor).initializeFromMWAggregateDescriptor(this);
}
protected void initializeFromMWMappingDescriptor(MWMappingDescriptor oldDescriptor) {
super.initializeFromMWMappingDescriptor(oldDescriptor);
Iterator mappings = mappings();
while (mappings.hasNext()) {
MWMapping mapping = (MWMapping) mappings.next();
mapping.parentDescriptorMorphedToAggregate();
}
getInheritancePolicy().parentDescriptorMorphedToAggregate();
}
public void initializeFromMWRelationalClassDescriptor(MWRelationalClassDescriptor oldDescriptor) {
super.initializeFromMWRelationalClassDescriptor(oldDescriptor);
for (Iterator i = userDefinedQueryKeys(); i.hasNext(); ){
((MWUserDefinedQueryKey) i.next()).setColumn(null);
}
}
public boolean isAggregateDescriptor() {
return true;
}
public void applyAdvancedPolicyDefaults(MWProjectDefaultsPolicy defaultsPolicy) {
defaultsPolicy.applyAdvancedPolicyDefaults(this);
}
//******************* Problem Handling *******************
protected void addProblemsTo(List newProblems) {
super.addProblemsTo(newProblems);
this.checkReferences(newProblems);
this.checkSharedAggregates(newProblems);
}
protected void checkMultipleMappingsWriteField(List newProblems) {
// override this method to do nothing
}
protected String multipleMappingsWriteFieldProblemResourceStringKey() {
throw new UnsupportedOperationException();
}
private void checkReferences(List newProblems) {
// If the descriptor is an aggregate then other classes
// cannot reference the aggregate with one-to-one,
// one-to-many, or many-to-many mappings.
// avoid null pointer exception when removing a descriptor
for (Iterator allDescriptors = this.getProject().mappingDescriptors(); allDescriptors.hasNext(); ) {
MWMappingDescriptor descriptor = (MWMappingDescriptor) allDescriptors.next();
for (Iterator mappings = descriptor.mappings(); mappings.hasNext(); ) {
MWMapping mapping = (MWMapping) mappings.next();
if (mapping instanceof MWAbstractTableReferenceMapping) {
MWAbstractTableReferenceMapping tableRefMapping = (MWAbstractTableReferenceMapping) mapping;
if (tableRefMapping.getReferenceDescriptor() == this) {
newProblems.add(this.buildProblem(ProblemConstants.DESCRIPTOR_CLASSES_REFERENCE_AN_AGGREGATE_TARGET));
}
}
}
}
}
private void checkSharedAggregates(List newProblems) {
// If the descriptor is an aggregate that is shared by
// multiple source descriptors then it can't have
// a mapping that has a target object that references it.
// This means no one-to-many or many-to-many mappings and
// no one-to-one mappings where the target has a
// pointer to the aggregate.
// NOTE: I haven't implemented the one-to-one part
// check to see if the aggregate is shared
int count = 0;
// avoid null pointer exception when removing a descriptor
for (Iterator allDescriptors = this.getProject().mappingDescriptors(); allDescriptors.hasNext(); ) {
MWMappingDescriptor descriptor = (MWMappingDescriptor) allDescriptors.next();
for (Iterator mappings = descriptor.mappings(); mappings.hasNext(); ) {
MWMapping mapping = (MWMapping) mappings.next();
if (mapping instanceof MWAggregateMapping) {
MWAggregateMapping aggMapping = (MWAggregateMapping) mapping;
if (aggMapping.getReferenceDescriptor() == this) {
count++;
}
}
}
}
if (count < 2) {
return;
}
// we know that the aggregate is shared
// now check that it doesn't have one-to-many or
// many-to-many mappings.
for (Iterator mappings = this.mappings(); mappings.hasNext(); ) {
MWMapping mapping = (MWMapping) mappings.next();
if (mapping instanceof MWCollectionMapping) {
newProblems.add(this.buildProblem(ProblemConstants.DESCRIPTOR_SHARED_AGGREGATE_HAS_1_TO_M_OR_M_TO_M_MAPPINGS));
}
}
}
// **************** runtime conversion **********
protected ClassDescriptor buildBasicRuntimeDescriptor() {
RelationalDescriptor descriptor = new RelationalDescriptor();
descriptor.descriptorIsAggregate();
descriptor.setJavaClassName(getMWClass().getName());
return descriptor;
}
protected void adjustUserDefinedQueryKeys(ClassDescriptor runtimeDescriptor) {
for (Iterator queryKeys = userDefinedQueryKeys(); queryKeys.hasNext();) {
MWUserDefinedQueryKey queryKey = (MWUserDefinedQueryKey) queryKeys.next();
DirectQueryKey runtimeQueryKey = new DirectQueryKey();
runtimeQueryKey.setName(queryKey.getName());
runtimeQueryKey.setFieldName(queryKey.fieldNameForRuntime());
runtimeDescriptor.addQueryKey(runtimeQueryKey);
}
}
}