/******************************************************************************* * 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.xml; 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.xml.MWEisDescriptor; import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.xml.MWXmlDescriptor; import org.eclipse.persistence.tools.workbench.mappingsmodel.schema.MWSchemaContextComponent; import org.eclipse.persistence.tools.workbench.mappingsmodel.xml.MWXmlField; import org.eclipse.persistence.tools.workbench.mappingsmodel.xml.MWXmlNode; import org.eclipse.persistence.tools.workbench.mappingsmodel.xml.MWXpathContext; import org.eclipse.persistence.tools.workbench.mappingsmodel.xml.MWXpathSpec; import org.eclipse.persistence.tools.workbench.mappingsmodel.xml.SchemaChange; import org.eclipse.persistence.tools.workbench.utility.node.Node; import org.eclipse.persistence.eis.mappings.EISOneToManyMapping; import org.eclipse.persistence.eis.mappings.EISOneToOneMapping; import org.eclipse.persistence.oxm.XMLDescriptor; import org.eclipse.persistence.oxm.mappings.XMLCompositeObjectMapping; public final class MWXmlFieldPair extends MWModel implements MWXmlNode, MWXpathContext { // **************** Variables ********************************************* private MWXmlField sourceXmlField; private MWXmlField targetXmlField; // **************** Constructors *************** /** Default constructor - for TopLink use only */ protected MWXmlFieldPair() { super(); } MWXmlFieldPair(MWXmlReferenceMapping parent) { super(parent); } MWXmlFieldPair(MWXmlReferenceMapping parent, String sourceXpath, String targetXpath) { this(parent); this.sourceXmlField.setXpath(sourceXpath); this.targetXmlField.setXpath(targetXpath); } // **************** Initialization **************************************** /** initialize persistent state */ protected void initialize(Node parent) { super.initialize(parent); this.sourceXmlField = new MWXmlField(this); this.targetXmlField = new MWXmlField(this); } protected void addChildrenTo(List children) { super.addChildrenTo(children); children.add(this.sourceXmlField); children.add(this.targetXmlField); } // **************** Source field ****************************************** public MWXmlField getSourceXmlField() { return this.sourceXmlField; } // **************** Target field ****************************************** public MWXmlField getTargetXmlField() { return this.targetXmlField; } // **************** MWXpathContext implementation ************************ public MWSchemaContextComponent schemaContext(MWXmlField xmlField) { if (xmlField == this.getTargetXmlField()) { MWXmlDescriptor xmlReferenceDescriptor = this.xmlReferenceDescriptor(); return (xmlReferenceDescriptor == null) ? null: xmlReferenceDescriptor.getSchemaContext(); } else { return this.xmlDescriptor().getSchemaContext(); } } public MWXpathSpec xpathSpec(MWXmlField xmlField) { return this.buildXpathSpec(xmlField); } protected MWXpathSpec buildXpathSpec(final MWXmlField xmlField) { return new MWXpathSpec() { public boolean mayUseCollectionData() { return MWXmlFieldPair.this.mayUseCollectionXpath(xmlField); } public boolean mayUseComplexData() { return false; } public boolean mayUseSimpleData() { return true; } }; } protected boolean mayUseCollectionXpath(MWXmlField xmlField) { if (xmlField == this.getSourceXmlField()) { return this.xmlRefMapping().sourceFieldMayUseCollectionXpath(); } else { return false; } } // **************** Convenience ******************************************* private MWXmlDescriptor xmlDescriptor() { return (MWXmlDescriptor) this.xmlRefMapping().getParent(); } private MWXmlReferenceMapping xmlRefMapping() { return (MWXmlReferenceMapping) this.getParent(); } private MWXmlDescriptor xmlReferenceDescriptor() { return this.xmlRefMapping().referenceDescriptor(); } // **************** Model synchronization ********************************* /** @see MWXmlNode#resolveXpaths */ public void resolveXpaths() { this.sourceXmlField.resolveXpaths(); this.targetXmlField.resolveXpaths(); } /** @see MWXmlNode#schemaChanged(SchemaChange) */ public void schemaChanged(SchemaChange change) { this.sourceXmlField.schemaChanged(change); this.targetXmlField.schemaChanged(change); } // **************** Problem handling ************************************** protected void addProblemsTo(List currentProblems) { super.addProblemsTo(currentProblems); this.addSourceFieldMissingProblemTo(currentProblems); this.addTargetFieldMissingProblemTo(currentProblems); } private void addSourceFieldMissingProblemTo(List newProblems) { if (! this.getSourceXmlField().isSpecified()) { newProblems.add(this.buildProblem(ProblemConstants.MAPPING_SOURCE_XPATH_MISSING)); } } private void addTargetFieldMissingProblemTo(List newProblems) { if (! this.getTargetXmlField().isSpecified()) { newProblems.add(this.buildProblem(ProblemConstants.MAPPING_TARGET_XPATH_MISSING)); } } /** Return true if the xpath is used by another source field */ public boolean duplicateSourceXpath(String xpath) { if (xpath.equals("")) { return false; } for (Iterator stream = this.xmlRefMapping().xmlFieldPairs(); stream.hasNext(); ) { MWXmlFieldPair fieldPair = (MWXmlFieldPair) stream.next(); if (fieldPair != this && xpath.equals(fieldPair.getSourceXmlField().getXpath())) { return true; } } return false; } /** Return true if the xpath specified by the xml field is used by another target field */ public boolean duplicateTargetXpath(String xpath) { if (xpath.equals("")) { return false; } for (Iterator stream = this.xmlRefMapping().xmlFieldPairs(); stream.hasNext(); ) { MWXmlFieldPair fieldPair = (MWXmlFieldPair) stream.next(); if (fieldPair != this && xpath.equals(fieldPair.getTargetXmlField().getXpath())) { return true; } } return false; } // **************** Runtime conversion ************************************ public void addRuntimeForeignKeyField(EISOneToOneMapping mapping) { if (this.getSourceXmlField().isSpecified() && this.getTargetXmlField().isSpecified()) { mapping.addForeignKeyField(this.getSourceXmlField().runtimeField(), this.getTargetXmlField().runtimeField()); } } public void addRuntimeForeignKeyField(EISOneToManyMapping mapping, MWXmlField groupingElement) { if (this.getSourceXmlField().isSpecified()&& this.getTargetXmlField().isSpecified()) { mapping.addForeignKeyField( this.getSourceXmlField().runtimeField(groupingElement), this.getTargetXmlField().runtimeField(groupingElement) ); } } // **************** TopLink Only Methods ********************************** public static XMLDescriptor buildDescriptor() { XMLDescriptor descriptor = new XMLDescriptor(); descriptor.setJavaClass(MWXmlFieldPair.class); XMLCompositeObjectMapping sourceFieldMapping = new XMLCompositeObjectMapping(); sourceFieldMapping.setReferenceClass(MWXmlField.class); sourceFieldMapping.setAttributeName("sourceXmlField"); sourceFieldMapping.setGetMethodName("getSourceXmlFieldForTopLink"); sourceFieldMapping.setSetMethodName("setSourceXmlFieldForTopLink"); sourceFieldMapping.setXPath("source-xml-field"); descriptor.addMapping(sourceFieldMapping); XMLCompositeObjectMapping targetFieldMapping = new XMLCompositeObjectMapping(); targetFieldMapping.setReferenceClass(MWXmlField.class); targetFieldMapping.setAttributeName("targetXmlDataFieldHandle"); targetFieldMapping.setGetMethodName("getTargetXmlFieldForTopLink"); targetFieldMapping.setSetMethodName("setTargetXmlFieldForTopLink"); targetFieldMapping.setXPath("target-xml-field"); descriptor.addMapping(targetFieldMapping); return descriptor; } private MWXmlField getSourceXmlFieldForTopLink() { return (this.sourceXmlField.isSpecified()) ? this.sourceXmlField : null; } private void setSourceXmlFieldForTopLink(MWXmlField xmlField) { this.sourceXmlField = ((xmlField == null) ? new MWXmlField(this) : xmlField); } private MWXmlField getTargetXmlFieldForTopLink() { return (this.targetXmlField.isSpecified()) ? this.targetXmlField : null; } private void setTargetXmlFieldForTopLink(MWXmlField xmlField) { this.targetXmlField = ((xmlField == null) ? new MWXmlField(this) : xmlField); } }