/******************************************************************************* * 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.mapping.relational; import java.util.Collection; import java.util.List; import org.eclipse.persistence.tools.workbench.mappingsmodel.MWModel; import org.eclipse.persistence.tools.workbench.mappingsmodel.MWQueryKey; import org.eclipse.persistence.tools.workbench.mappingsmodel.ProblemConstants; import org.eclipse.persistence.tools.workbench.mappingsmodel.db.MWColumn; import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.MWDescriptor; import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.MWMappingDescriptor; import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.relational.MWRelationalClassDescriptor; import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.relational.MWRelationalDescriptor; import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.relational.MWTableDescriptor; import org.eclipse.persistence.tools.workbench.mappingsmodel.handles.MWColumnHandle; import org.eclipse.persistence.tools.workbench.mappingsmodel.handles.MWHandle; import org.eclipse.persistence.tools.workbench.mappingsmodel.handles.MWHandle.NodeReferenceScrubber; import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.MWConverterMapping; import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.MWDirectMapping; import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.MWTypeConversionConverter; import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.MWClassAttribute; import org.eclipse.persistence.tools.workbench.utility.CollectionTools; import org.eclipse.persistence.tools.workbench.utility.node.Node; import org.eclipse.persistence.mappings.DatabaseMapping; import org.eclipse.persistence.mappings.DirectToFieldMapping; import org.eclipse.persistence.oxm.XMLDescriptor; import org.eclipse.persistence.oxm.mappings.XMLCompositeObjectMapping; public abstract class MWRelationalDirectMapping extends MWDirectMapping implements AggregateRuntimeFieldNameGenerator { // **************** Variables ********************************************* private MWColumnHandle columnHandle; public final static String COLUMN_PROPERTY = "column"; /** * The auto-generated query key for this mapping. This should * not be made persistent, as it is initialized by instances of * this class and basically just encapsulates some of the behavior * of itself. */ private AutoGeneratedQueryKey autoGeneratedQueryKey; // **************** Constructors *************** /** Default constructor - for TopLink use only */ protected MWRelationalDirectMapping() { super(); } protected MWRelationalDirectMapping(MWMappingDescriptor parent, MWClassAttribute attribute, String name) { super(parent, attribute, name); } // **************** Initialization **************************************** protected void initialize() { super.initialize(); this.autoGeneratedQueryKey = new AutoGeneratedQueryKey(this); } /** initialize persistent state */ protected void initialize(Node parent) { super.initialize(parent); this.columnHandle = new MWColumnHandle(this, this.buildColumnScrubber()); } // **************** MWMapping override **************** public void setName(String name) { String oldName = this.getName(); super.setName(name); String newName = this.getName(); if (this.attributeValueHasChanged(oldName, newName)) { this.autoGeneratedQueryKey.nameChanged(oldName, newName); } } // **************** MWDirectMapping implementation **************** protected MWTypeConversionConverter buildTypeConversionConverter() { return new MWRelationalTypeConversionConverter(this); } // **************** MWRelationalMapping implementation **************** public boolean parentDescriptorIsAggregate() { return ((MWRelationalDescriptor) getParentDescriptor()).isAggregateDescriptor(); } public MWRelationalDescriptor getParentRelationalDescriptor() { return (MWRelationalDescriptor) getParentDescriptor(); } // **************** Column ************************************************* public MWColumn getColumn() { return this.columnHandle.getColumn(); } public void setColumn(MWColumn column) { Object old = this.columnHandle.getColumn(); this.columnHandle.setColumn(column); this.firePropertyChanged(COLUMN_PROPERTY, old, column); } // **************** Auto generated query key ****************************** /** * Returns an auto-generated query key for this mapping. * Because the behavior of the query key mimics some of that of * this mapping, it is basically just a "window" into the * direct mapping. */ public MWQueryKey getAutoGeneratedQueryKey() { return this.autoGeneratedQueryKey; } // **************** icon key ********************************************** public abstract String iconKey(); // **************** MWRelationalMapping implementation ***************** public void addWrittenFieldsTo(Collection writtenFields) { if (isReadOnly()) { return; } if (getColumn() != null) { writtenFields.add(getColumn()); } } // ************* aggregate support ************* public String fieldNameForRuntime() { return "DIRECT"; } public AggregateFieldDescription fullFieldDescription() { return new AggregateFieldDescription() { public String getMessageKey() { return "AGGREGATE_FIELD_DESCRIPTION_FOR_DIRECT_MAPPING"; } public Object[] getMessageArguments() { return new Object[] {}; } }; } protected Collection buildAggregateFieldNameGenerators() { Collection aggregateFieldNameGenerators = super.buildAggregateFieldNameGenerators(); aggregateFieldNameGenerators.add(this); return aggregateFieldNameGenerators; } public void parentDescriptorMorphedToAggregate() { super.parentDescriptorMorphedToAggregate(); setColumn(null); } public boolean fieldIsWritten() { return true; } public MWDescriptor owningDescriptor() { return (MWDescriptor) this.getParent(); } // **************** Containment hierarchy ****************************** protected void addChildrenTo(List children) { super.addChildrenTo(children); children.add(this.autoGeneratedQueryKey); // ??? ~bjv children.add(this.columnHandle); } private NodeReferenceScrubber buildColumnScrubber() { return new NodeReferenceScrubber() { public void nodeReferenceRemoved(Node node, MWHandle handle) { MWRelationalDirectMapping.this.setColumn(null); } public String toString() { return "MWRelationalDirectMapping.buildColumnScrubber()"; } }; } // **************** Mapping Morphing support ****************************** public void initializeFromMWRelationalDirectMapping(MWRelationalDirectMapping mapping) { super.initializeFromMWRelationalDirectMapping(mapping); this.setColumn(mapping.getColumn()); } protected void initializeFromMWConverterMapping(MWConverterMapping converterMapping) { // do nothing - this mapping doesn't like to change converters } // **************** Problem Handling ************************************** protected void addProblemsTo(List newProblems) { super.addProblemsTo(newProblems); this.checkColumn(newProblems); } private void checkColumn(List newProblems) { if (this.parentDescriptorIsAggregate()) { return; } if (this.getColumn() == null) { newProblems.add(this.buildProblem(ProblemConstants.MAPPING_FIELD_NOT_SPECIFIED)); } else { if ( ! CollectionTools.contains(((MWTableDescriptor) this.getParentDescriptor()).allAssociatedColumns(), this.getColumn())) { newProblems.add(this.buildProblem(ProblemConstants.MAPPING_FIELD_NOT_VALID)); } } } // **************** Automap Support *************************************** public void addColumnlessDirectMappingTo(Collection columnlessDirectMappings) { if (this.getColumn() == null) { columnlessDirectMappings.add(this); } } // **************** Runtime Conversion **************** public DatabaseMapping runtimeMapping() { DirectToFieldMapping mapping = (DirectToFieldMapping) super.runtimeMapping(); if (parentDescriptorIsAggregate()) { mapping.setFieldName(getName() + "->" + fieldNameForRuntime()); } else if (getColumn() != null) { mapping.setFieldName(getColumn().qualifiedName()); } else { mapping.setFieldName(""); } return mapping; } // **************** TopLink methods *************************************** public static XMLDescriptor buildDescriptor() { XMLDescriptor descriptor = new XMLDescriptor(); descriptor.setJavaClass(MWRelationalDirectMapping.class); descriptor.getInheritancePolicy().setParentClass(MWDirectMapping.class); XMLCompositeObjectMapping columnHandleMapping = new XMLCompositeObjectMapping(); columnHandleMapping.setAttributeName("columnHandle"); columnHandleMapping.setGetMethodName("getColumnHandleForTopLink"); columnHandleMapping.setSetMethodName("setColumnHandleForTopLink"); columnHandleMapping.setReferenceClass(MWColumnHandle.class); columnHandleMapping.setXPath("column-handle"); descriptor.addMapping(columnHandleMapping); return descriptor; } /** check for null */ private MWColumnHandle getColumnHandleForTopLink() { return (this.columnHandle.getColumn() == null) ? null : this.columnHandle; } private void setColumnHandleForTopLink(MWColumnHandle handle) { NodeReferenceScrubber scrubber = this.buildColumnScrubber(); this.columnHandle = ((handle == null) ? new MWColumnHandle(this, scrubber) : handle.setScrubber(scrubber)); } // **************** Member classes **************************************** private static final class AutoGeneratedQueryKey extends MWModel implements MWQueryKey { AutoGeneratedQueryKey(MWRelationalDirectMapping parent) { super(parent); } private MWRelationalDirectMapping getMapping() { return (MWRelationalDirectMapping) this.getParent(); } public MWColumn getColumn() { return this.getMapping().getColumn(); } public boolean isAutoGenerated() { return true; } public MWRelationalClassDescriptor getDescriptor() { return (MWRelationalClassDescriptor) this.getMapping().getParentDescriptor(); } public String getName() { return this.getMapping().getName(); } void nameChanged(String oldName, String newName) { this.firePropertyChanged(NAME_PROPERTY, oldName, newName); } public String displayString() { return this.getName(); } public void toString(StringBuffer sb) { sb.append("field="); if (getColumn() == null) { sb.append("null"); } else { getColumn().toString(sb); } } } }