/******************************************************************************* * 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.Collection; import java.util.List; import org.eclipse.persistence.tools.workbench.mappingsmodel.ProblemConstants; import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.xml.MWOXDescriptor; import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.xml.MWXmlDescriptor; import org.eclipse.persistence.tools.workbench.mappingsmodel.mapping.MWMapping; import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.MWClassAttribute; 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.oxm.XMLDescriptor; import org.eclipse.persistence.oxm.mappings.XMLCompositeObjectMapping; import org.eclipse.persistence.oxm.mappings.XMLDirectMapping; public abstract class MWAbstractAnyMapping extends MWMapping implements MWXmlMapping, MWXpathedMapping, MWXpathContext { // **************** Variables ********************************************* private MWXmlField xmlField; private volatile boolean wildcardMapping; public static final String WILDCARD_PROPERTY = "wildcardMapping"; // **************** Constructors ****************************************** /** Default constructor - for TopLink use only */ protected MWAbstractAnyMapping() { super(); } protected MWAbstractAnyMapping(MWXmlDescriptor descriptor, MWClassAttribute attribute, String name) { super(descriptor, attribute, name); } // **************** Initialization **************************************** protected void initialize(Node parent) { super.initialize(parent); this.xmlField = new MWXmlField(this); } protected void addChildrenTo(List children) { super.addChildrenTo(children); children.add(this.xmlField); } // **************** MWXpathedMapping implementation ********************** public MWXmlField getXmlField() { return this.xmlField; } // **************** Wildcard mapping ************************************** public boolean isWildcardMapping() { return this.wildcardMapping; } public void setWildcardMapping(boolean newValue) { boolean oldValue = this.wildcardMapping; this.wildcardMapping = newValue; this.firePropertyChanged(WILDCARD_PROPERTY, oldValue, newValue); } // **************** MWXmlMapping contract ********************************* public MWSchemaContextComponent schemaContext() { return this.oxDescriptor().getSchemaContext(); } public MWXmlField firstMappedXmlField() { if (this.getXmlField().isResolved()) { return this.getXmlField(); } else { return null; } } public void addWrittenFieldsTo(Collection writtenFields) { if (! this.isReadOnly() && ! this.getXmlField().getXpath().equals("")) { writtenFields.add(this.getXmlField()); } } // **************** MWXpathContext implementation ************************ public MWSchemaContextComponent schemaContext(MWXmlField xmlField) { return this.schemaContext(); } public MWXpathSpec xpathSpec(MWXmlField xmlField) { return this.buildXpathSpec(); } protected MWXpathSpec buildXpathSpec() { return new MWXpathSpec() { public boolean mayUseCollectionData() { return MWAbstractAnyMapping.this.mayUseCollectionData(); } public boolean mayUseComplexData() { return true; } public boolean mayUseSimpleData() { return false; } }; } protected abstract boolean mayUseCollectionData(); // **************** Convenience ******************************************* protected MWOXDescriptor oxDescriptor() { return (MWOXDescriptor) this.getParent(); } // **************** Morphing ********************************************** protected void initializeFromMWXpathedMapping(MWXpathedMapping oldMapping) { super.initializeFromMWXpathedMapping(oldMapping); this.getXmlField().setXpath(oldMapping.getXmlField().getXpath()); // can't use typed, so don't set that } // **************** Problem handling ************************************** protected void addProblemsTo(List newProblems) { // would like to add xpath and reference descriptor problems first this.addXmlFieldProblemsTo(newProblems); this.addWildcardProblemsTo(newProblems); super.addProblemsTo(newProblems); } protected void addXmlFieldProblemsTo(List newProblems) { if (! this.oxDescriptor().isAnyTypeDescriptor()) { this.addXpathNotSpecifiedProblemTo(newProblems); } } private void addXpathNotSpecifiedProblemTo(List newProblems) { if (!this.oxDescriptor().isAnyTypeDescriptor() && !this.getXmlField().isSpecified()) { newProblems.add(this.buildProblem(ProblemConstants.XPATH_NOT_SPECIFIED)); } } private void addWildcardProblemsTo(List newProblems) { this.addWildcardSpecifiedProblemTo(newProblems); this.addNoWildcardInSchemaContextProblemTo(newProblems); this.addMapsToNonAttributesProblemTo(newProblems); } private void addWildcardSpecifiedProblemTo(List newProblems) { // if this is in an anyType descriptor, it cannot be a wildcard mapping if (this.oxDescriptor().isAnyTypeDescriptor() && this.isWildcardMapping()) { newProblems.add(this.buildProblem(ProblemConstants.MAPPING_WILDCARD_SPECIFIED_IN_ANY_TYPE_DESCRIPTOR)); } } private void addNoWildcardInSchemaContextProblemTo(List newProblems) { if (this.isWildcardMapping()) { MWSchemaContextComponent context = this.schemaContext(); if (context != null && ! context.containsWildcard()) { newProblems.add(this.buildProblem(ProblemConstants.MAPPING_NO_WILDCARD_IN_SCHEMA_CONTEXT)); } } } private void addMapsToNonAttributesProblemTo(List newProblems) { // TODO !!! // The descriptor that owns this mapping may not map to any xml fields that // conflict with the element content of this mapping. // // If this mapping has no xpath, then its context is also the context of // the owning descriptor, and the owning descriptor may not map to any xml // fields that are not attributes. // // If this mapping has an xpath, then its context is the context of that // xpath, and the descriptor may not map to any xml fields within that context // that are not attributes. // (Will likely need to have an iterator on all xml fields mapped to by // the owning descriptor) } // **************** Model synchronization ********************************* /** @see MWXmlNode#resolveXpaths */ public void resolveXpaths() { this.xmlField.resolveXpaths(); } /** @see MWXmlNode#schemaChanged(SchemaChange) */ public void schemaChanged(SchemaChange change) { this.xmlField.schemaChanged(change); } // **************** TopLink methods *************************************** public static XMLDescriptor buildDescriptor() { XMLDescriptor descriptor = new XMLDescriptor(); descriptor.setJavaClass(MWAbstractAnyMapping.class); descriptor.descriptorIsAggregate(); descriptor.getInheritancePolicy().setParentClass(MWMapping.class); XMLCompositeObjectMapping xmlFieldMapping = new XMLCompositeObjectMapping(); xmlFieldMapping.setReferenceClass(MWXmlField.class); xmlFieldMapping.setAttributeName("xmlField"); xmlFieldMapping.setGetMethodName("getXmlFieldForTopLink"); xmlFieldMapping.setSetMethodName("setXmlFieldForTopLink"); xmlFieldMapping.setXPath("xpath"); descriptor.addMapping(xmlFieldMapping); ((XMLDirectMapping) descriptor.addDirectMapping("wildcardMapping", "wildcard-mapping/text()")).setNullValue(Boolean.FALSE); return descriptor; } private MWXmlField getXmlFieldForTopLink() { return (this.xmlField.isSpecified()) ? this.xmlField: null; } private void setXmlFieldForTopLink(MWXmlField xmlField) { this.xmlField = ((xmlField == null) ? new MWXmlField(this) : xmlField); } }