blob: ac5290d5dd5e1abcb78a404f7436d61da5627b93 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2013 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0, which accompanies this distribution
* and is available at http://www.eclipse.org/legal/epl-v10.html.
*
* Contributors:
* Oracle - initial API and implementation
******************************************************************************/
package org.eclipse.jpt.jaxb.core.internal.context.java;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jpt.common.core.internal.utility.TypeTools;
import org.eclipse.jpt.common.core.resource.java.JavaResourceType;
import org.eclipse.jpt.common.core.utility.TextRange;
import org.eclipse.jpt.common.utility.collection.Bag;
import org.eclipse.jpt.common.utility.internal.ObjectTools;
import org.eclipse.jpt.common.utility.internal.StringTools;
import org.eclipse.jpt.common.utility.internal.collection.CollectionTools;
import org.eclipse.jpt.common.utility.internal.iterable.EmptyIterable;
import org.eclipse.jpt.common.utility.internal.iterable.EmptyListIterable;
import org.eclipse.jpt.common.utility.internal.iterable.IterableTools;
import org.eclipse.jpt.common.utility.internal.iterable.SingleElementIterable;
import org.eclipse.jpt.common.utility.iterable.ListIterable;
import org.eclipse.jpt.jaxb.core.MappingKeys;
import org.eclipse.jpt.jaxb.core.context.JaxbAttributeMapping;
import org.eclipse.jpt.jaxb.core.context.JaxbAttributesContainer;
import org.eclipse.jpt.jaxb.core.context.JaxbAttributesContainer.Context;
import org.eclipse.jpt.jaxb.core.context.JaxbClassMapping;
import org.eclipse.jpt.jaxb.core.context.JaxbPackage;
import org.eclipse.jpt.jaxb.core.context.JaxbPackageInfo;
import org.eclipse.jpt.jaxb.core.context.JaxbPersistentAttribute;
import org.eclipse.jpt.jaxb.core.context.XmlAccessOrder;
import org.eclipse.jpt.jaxb.core.context.XmlAccessType;
import org.eclipse.jpt.jaxb.core.context.XmlNamedNodeMapping;
import org.eclipse.jpt.jaxb.core.context.java.JavaClass;
import org.eclipse.jpt.jaxb.core.context.java.JavaClassMapping;
import org.eclipse.jpt.jaxb.core.context.java.JavaPersistentAttribute;
import org.eclipse.jpt.jaxb.core.context.java.JavaType;
import org.eclipse.jpt.jaxb.core.resource.java.JAXB;
import org.eclipse.jpt.jaxb.core.resource.java.XmlAccessorOrderAnnotation;
import org.eclipse.jpt.jaxb.core.resource.java.XmlAccessorTypeAnnotation;
import org.eclipse.jpt.jaxb.core.validation.JptJaxbCoreValidationMessages;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
public class GenericJavaClassMapping
extends AbstractJavaTypeMapping
implements JavaClassMapping {
protected String specifiedFactoryClass;
protected String factoryMethod;
protected final PropOrderContainer propOrderContainer;
protected String superclassName; // used internally only
protected static final String SUPERCLASSNAME_PROPERTY = "superclassName"; //$NON-NLS-1$ - used only to trigger update
protected JaxbClassMapping superclass;
protected XmlAccessType accessType;
protected XmlAccessType defaultAccessType;
protected XmlAccessType specifiedAccessType;
protected XmlAccessOrder defaultAccessOrder;
protected XmlAccessOrder specifiedAccessOrder;
protected boolean hasRootElementInHierarchy_loaded = false;
protected boolean hasRootElementInHierarchy = false;
protected final JaxbAttributesContainer attributesContainer;
protected final Map<JaxbClassMapping, JaxbAttributesContainer> includedAttributesContainers;
public GenericJavaClassMapping(JavaClass parent) {
super(parent);
this.includedAttributesContainers = new Hashtable<JaxbClassMapping, JaxbAttributesContainer>();
this.propOrderContainer = new PropOrderContainer();
initFactoryClass();
initFactoryMethod();
initPropOrder();
initAccessType();
initSpecifiedAccessOrder();
initDefaultAccessOrder();
initSuperclassName();
this.attributesContainer = new GenericJavaAttributesContainer(this, buildAttributesContainerOwner(), getJavaResourceType());
}
@Override
public JavaResourceType getJavaResourceType() {
return (JavaResourceType) super.getJavaResourceType();
}
@Override
public JavaClass getJavaType() {
return (JavaClass) super.getJavaType();
}
public JaxbPackageInfo getPackageInfo() {
JaxbPackage jaxbPackage = getJaxbPackage();
// jaxb package may be null during initialization/update
return (jaxbPackage == null) ? null : jaxbPackage.getPackageInfo();
}
// ***** sync/update *****
@Override
public void synchronizeWithResourceModel() {
super.synchronizeWithResourceModel();
syncFactoryClass();
syncFactoryMethod();
syncPropOrder();
syncAccessType();
syncSpecifiedAccessOrder();
syncSuperclassName();
this.attributesContainer.synchronizeWithResourceModel();
syncIncludedAttributes();
}
@Override
public void update() {
super.update();
updateSuperclass(); // done first because much depends on it
updateAccessType();
updateDefaultAccessOrder();
this.hasRootElementInHierarchy_loaded = false; // triggers that the value must be recalculated on next request
this.attributesContainer.update();
updateIncludedAttributes();
}
// ***** factory class *****
public String getFactoryClass() {
return (this.specifiedFactoryClass != null) ? this.specifiedFactoryClass : JAXB.XML_TYPE__DEFAULT_FACTORY_CLASS;
}
public String getSpecifiedFactoryClass() {
return this.specifiedFactoryClass;
}
public void setSpecifiedFactoryClass(String factoryClass) {
getXmlTypeAnnotation().setFactoryClass(factoryClass);
setSpecifiedFactoryClass_(factoryClass);
}
protected void setSpecifiedFactoryClass_(String factoryClass) {
String old = this.specifiedFactoryClass;
this.specifiedFactoryClass = factoryClass;
firePropertyChanged(SPECIFIED_FACTORY_CLASS_PROPERTY, old, factoryClass);
}
protected String getResourceFactoryClass() {
return getXmlTypeAnnotation().getFactoryClass();
}
protected void initFactoryClass() {
this.specifiedFactoryClass = getResourceFactoryClass();
}
protected void syncFactoryClass() {
setSpecifiedFactoryClass_(getResourceFactoryClass());
}
// ***** factory method *****
public String getFactoryMethod() {
return this.factoryMethod;
}
public void setFactoryMethod(String factoryMethod) {
getXmlTypeAnnotation().setFactoryMethod(factoryMethod);
setFactoryMethod_(factoryMethod);
}
protected void setFactoryMethod_(String factoryMethod) {
String old = this.factoryMethod;
this.factoryMethod = factoryMethod;
firePropertyChanged(FACTORY_METHOD_PROPERTY, old, factoryMethod);
}
protected String getResourceFactoryMethod() {
return getXmlTypeAnnotation().getFactoryMethod();
}
protected void initFactoryMethod() {
this.factoryMethod = getResourceFactoryMethod();
}
protected void syncFactoryMethod() {
setFactoryMethod_(getResourceFactoryMethod());
}
// ***** prop order *****
public ListIterable<String> getPropOrder() {
return this.propOrderContainer.getContextElements();
}
public String getProp(int index) {
return this.propOrderContainer.getContextElement(index);
}
public int getPropOrderSize() {
return this.propOrderContainer.getContextElementsSize();
}
public void addProp(int index, String prop) {
getXmlTypeAnnotation().addProp(index, prop);
this.propOrderContainer.addContextElement(index, prop);
}
public void removeProp(String prop) {
this.removeProp(this.propOrderContainer.indexOfContextElement(prop));
}
public void removeProp(int index) {
this.getXmlTypeAnnotation().removeProp(index);
this.propOrderContainer.removeContextElement(index);
}
public void moveProp(int targetIndex, int sourceIndex) {
this.getXmlTypeAnnotation().moveProp(targetIndex, sourceIndex);
this.propOrderContainer.moveContextElement(targetIndex, sourceIndex);
}
protected void initPropOrder() {
this.propOrderContainer.initialize();
}
protected void syncPropOrder() {
this.propOrderContainer.synchronizeWithResourceModel();
}
protected ListIterable<String> getResourcePropOrder() {
ListIterable<String> result = getXmlTypeAnnotation().getPropOrder();
if (IterableTools.size(result) == 1 && StringTools.EMPTY_STRING.equals(IterableTools.get(result, 0))) {
return EmptyListIterable.instance();
}
return result;
}
// ***** XmlAccessorType *****
public XmlAccessType getAccessType() {
return this.accessType;
}
protected void setAccessType_(XmlAccessType accessType) {
XmlAccessType old = this.accessType;
this.accessType = accessType;
firePropertyChanged(ACCESS_TYPE_PROPERTY, old, accessType);
}
public XmlAccessType getDefaultAccessType() {
return this.defaultAccessType;
}
protected void setDefaultAccessType_(XmlAccessType access) {
XmlAccessType old = this.defaultAccessType;
this.defaultAccessType = access;
firePropertyChanged(DEFAULT_ACCESS_TYPE_PROPERTY, old, access);
}
public XmlAccessType getSpecifiedAccessType() {
return this.specifiedAccessType;
}
public void setSpecifiedAccessType(XmlAccessType access) {
getXmlAccessorTypeAnnotation().setValue(XmlAccessType.toJavaResourceModel(access));
setSpecifiedAccessType_(access);
}
protected void setSpecifiedAccessType_(XmlAccessType access) {
XmlAccessType old = this.specifiedAccessType;
this.specifiedAccessType = access;
firePropertyChanged(SPECIFIED_ACCESS_TYPE_PROPERTY, old, access);
}
protected void initAccessType() {
this.specifiedAccessType = getResourceAccessType();
}
protected void syncAccessType() {
setSpecifiedAccessType(getResourceAccessType());
}
protected void updateAccessType() {
setDefaultAccessType_(buildDefaultAccessType());
XmlAccessType actual = (this.specifiedAccessType != null) ?
this.specifiedAccessType
: this.defaultAccessType;
setAccessType_(actual);
}
/**
* Default access type is determined by the following, in order of precedence:
* - @XmlAccessorType annotation on a mapped (or transient, apparently) super class
* - @XmlAccessorType annotation on the package
* - default access type of {@link XmlAccessType#PUBLIC_MEMBER}
*/
protected XmlAccessType buildDefaultAccessType() {
XmlAccessType accessType = getSuperclassAccessType();
if (accessType != null) {
return accessType;
}
accessType = getPackageAccessType();
if (accessType != null) {
return accessType;
}
return XmlAccessType.PUBLIC_MEMBER;
}
protected XmlAccessType getSuperclassAccessType() {
JaxbClassMapping superclass = this.superclass;
while (superclass != null) {
XmlAccessType accessType = superclass.getSpecifiedAccessType();
if (accessType != null) {
return accessType;
}
superclass = superclass.getSuperclass();
}
return null;
}
protected XmlAccessType getPackageAccessType() {
JaxbPackageInfo packageInfo = getPackageInfo();
return (packageInfo == null) ? null : packageInfo.getAccessType();
}
protected XmlAccessorTypeAnnotation getXmlAccessorTypeAnnotation() {
return (XmlAccessorTypeAnnotation) getJavaResourceType().getNonNullAnnotation(JAXB.XML_ACCESSOR_TYPE);
}
protected XmlAccessType getResourceAccessType() {
return XmlAccessType.fromJavaResourceModel(getXmlAccessorTypeAnnotation().getValue());
}
// ***** XmlAccessorOrder *****
public XmlAccessOrder getAccessOrder() {
return (this.specifiedAccessOrder != null) ? this.specifiedAccessOrder : this.defaultAccessOrder;
}
public XmlAccessOrder getDefaultAccessOrder() {
return this.defaultAccessOrder;
}
protected void setDefaultAccessOrder_(XmlAccessOrder accessOrder) {
XmlAccessOrder old = this.defaultAccessOrder;
this.defaultAccessOrder = accessOrder;
firePropertyChanged(DEFAULT_ACCESS_ORDER_PROPERTY, old, accessOrder);
}
public XmlAccessOrder getSpecifiedAccessOrder() {
return this.specifiedAccessOrder;
}
public void setSpecifiedAccessOrder(XmlAccessOrder accessOrder) {
getXmlAccessorOrderAnnotation().setValue(XmlAccessOrder.toJavaResourceModel(accessOrder));
setSpecifiedAccessOrder_(accessOrder);
}
protected void setSpecifiedAccessOrder_(XmlAccessOrder accessOrder) {
XmlAccessOrder old = this.specifiedAccessOrder;
this.specifiedAccessOrder = accessOrder;
firePropertyChanged(SPECIFIED_ACCESS_ORDER_PROPERTY, old, accessOrder);
}
protected void initDefaultAccessOrder() {
this.defaultAccessOrder = buildDefaultAccessOrder();
}
protected void updateDefaultAccessOrder() {
setDefaultAccessOrder_(buildDefaultAccessOrder());
}
/**
* Default access order is determined by the following, in order of precedence:
* - @XmlAccessorOrder annotation on a mapped (or transient, apparently) super class
* - @XmlAccessorOrder annotation on the package
* - default access order of {@link UNDEFINED}
*/
protected XmlAccessOrder buildDefaultAccessOrder() {
XmlAccessOrder accessOrder = getSuperclassAccessOrder();
if (accessOrder != null) {
return accessOrder;
}
accessOrder = getPackageAccessOrder();
if (accessOrder != null) {
return accessOrder;
}
return XmlAccessOrder.UNDEFINED;
}
protected XmlAccessOrder getSuperclassAccessOrder() {
JaxbClassMapping superclass = this.superclass;
while (superclass != null) {
XmlAccessOrder accessOrder = superclass.getSpecifiedAccessOrder();
if (accessOrder != null) {
return accessOrder;
}
superclass = superclass.getSuperclass();
}
return null;
}
protected XmlAccessOrder getPackageAccessOrder() {
JaxbPackageInfo packageInfo = getPackageInfo();
return packageInfo == null ? null : packageInfo.getAccessOrder();
}
protected XmlAccessorOrderAnnotation getXmlAccessorOrderAnnotation() {
return (XmlAccessorOrderAnnotation) getJavaResourceType().getNonNullAnnotation(JAXB.XML_ACCESSOR_ORDER);
}
protected XmlAccessOrder getResourceAccessOrder() {
return XmlAccessOrder.fromJavaResourceModel(getXmlAccessorOrderAnnotation().getValue());
}
protected void initSpecifiedAccessOrder() {
this.specifiedAccessOrder = getResourceAccessOrder();
}
protected void syncSpecifiedAccessOrder() {
setSpecifiedAccessOrder_(getResourceAccessOrder());
}
// ********** super class **********
protected void initSuperclassName() {
this.superclassName = getResourceSuperclassName();
}
protected void syncSuperclassName() {
String old = this.superclassName;
this.superclassName = getResourceSuperclassName();
firePropertyChanged(SUPERCLASSNAME_PROPERTY, old, this.superclassName);
}
protected String getResourceSuperclassName() {
return getJavaResourceType().getSuperclassQualifiedName();
}
public JaxbClassMapping getSuperclass() {
return this.superclass;
}
protected void setSuperclass_(JaxbClassMapping superclass) {
JaxbClassMapping old = this.superclass;
this.superclass = superclass;
this.firePropertyChanged(SUPERCLASS_PROPERTY, old, superclass);
}
protected void updateSuperclass() {
setSuperclass_(findSuperclass());
}
protected JaxbClassMapping findSuperclass() {
if (this.superclassName != null) {
return getJaxbProject().getContextRoot().getClassMapping(this.superclassName);
}
return null;
}
// ***** attributes *****
public Iterable<JavaPersistentAttribute> getAttributes() {
return this.attributesContainer.getAttributes();
}
public int getAttributesSize() {
return this.attributesContainer.getAttributesSize();
}
protected GenericJavaAttributesContainer.Context buildAttributesContainerOwner() {
return new GenericJavaAttributesContainer.Context() {
public XmlAccessType getAccessType() {
return GenericJavaClassMapping.this.getAccessType();
}
public void attributeAdded(JaxbPersistentAttribute attribute) {
GenericJavaClassMapping.this.fireItemAdded(ATTRIBUTES_COLLECTION, attribute);
}
public void attributeRemoved(JaxbPersistentAttribute attribute) {
GenericJavaClassMapping.this.fireItemRemoved(ATTRIBUTES_COLLECTION, attribute);
}
};
}
// ***** included attributes *****
public Iterable<JaxbPersistentAttribute> getIncludedAttributes() {
return IterableTools.children(getIncludedAttributesContainers(), JaxbAttributesContainer.ATTRIBUTES_TRANSFORMER);
}
protected Iterable<JaxbAttributesContainer> getIncludedAttributesContainers() {
return IterableTools.cloneLive(this.includedAttributesContainers.values()); // read-only
}
public int getIncludedAttributesSize() {
int size = 0;
for (JaxbAttributesContainer attributesContainer : getIncludedAttributesContainers()) {
size += attributesContainer.getAttributesSize();
}
return size;
}
protected void syncIncludedAttributes() {
for (JaxbAttributesContainer attributesContainer : this.includedAttributesContainers.values()) {
attributesContainer.synchronizeWithResourceModel();
}
}
protected void updateIncludedAttributes() {
HashSet<JaxbClassMapping> oldSuperclasses
= CollectionTools.set(this.includedAttributesContainers.keySet());
Set<JaxbPersistentAttribute> oldAttributes = CollectionTools.set(getIncludedAttributes());
if (! isXmlTransient()) {
JaxbClassMapping superclass = this.superclass;
// only add inherited attributes for superclasses up until a mapped class is encountered
while (superclass != null && superclass.isXmlTransient()) {
if (this.includedAttributesContainers.containsKey(superclass)) {
this.includedAttributesContainers.get(superclass).update();
oldSuperclasses.remove(superclass);
}
else {
this.includedAttributesContainers.put(superclass, buildIncludedAttributesContainer(superclass));
}
superclass = superclass.getSuperclass();
}
}
for (JaxbClassMapping oldSuperclass : oldSuperclasses) {
this.includedAttributesContainers.remove(oldSuperclass);
}
Set<JaxbPersistentAttribute> newAttributes = CollectionTools.set(getIncludedAttributes());
if (IterableTools.elementsAreDifferent(oldAttributes, newAttributes)) {
fireCollectionChanged(INCLUDED_ATTRIBUTES_COLLECTION, newAttributes);
}
}
protected JaxbAttributesContainer buildIncludedAttributesContainer(JaxbClassMapping classMapping) {
return classMapping.buildIncludedAttributesContainer(this, buildIncludedAttributesContainerOwner());
}
protected JaxbAttributesContainer.Context buildIncludedAttributesContainerOwner() {
return new GenericJavaAttributesContainer.Context() {
public XmlAccessType getAccessType() {
return GenericJavaClassMapping.this.getAccessType();
}
public void attributeAdded(JaxbPersistentAttribute attribute) {
GenericJavaClassMapping.this.fireItemAdded(INCLUDED_ATTRIBUTES_COLLECTION, attribute);
}
public void attributeRemoved(JaxbPersistentAttribute attribute) {
GenericJavaClassMapping.this.fireItemRemoved(INCLUDED_ATTRIBUTES_COLLECTION, attribute);
}
};
}
public JaxbAttributesContainer buildIncludedAttributesContainer(JaxbClassMapping parent, Context context) {
return new GenericJavaAttributesContainer(parent, context, getJavaResourceType());
}
// ***** misc attributes *****
public Iterable<JaxbPersistentAttribute> getAllLocallyDefinedAttributes() {
return IterableTools.concatenate(
getAttributes(),
getIncludedAttributes());
}
public Iterable<JaxbPersistentAttribute> getInheritedAttributes() {
return IterableTools.concatenate(
getIncludedAttributes(),
getOtherInheritedAttributes());
}
public Iterable<JaxbPersistentAttribute> getAllAttributes() {
return IterableTools.concatenate(
getAttributes(),
getIncludedAttributes(),
getOtherInheritedAttributes());
}
/**
* return those inherited attributes that are not included
*/
protected Iterable<JaxbPersistentAttribute> getOtherInheritedAttributes() {
return (this.superclass == null) ?
IterableTools.<JaxbPersistentAttribute>emptyIterable() :
IterableTools.children(
ObjectTools.chain(this.superclass, JaxbClassMapping.SUPER_CLASS_TRANSFORMER),
JaxbClassMapping.ATTRIBUTES_TRANSFORMER
);
}
// ***** subClasses *****
@Override
public boolean hasRootElementInHierarchy() {
if (! this.hasRootElementInHierarchy_loaded) {
this.hasRootElementInHierarchy = calculateHasRootElementInHierarchy();
this.hasRootElementInHierarchy_loaded = true;
}
return this.hasRootElementInHierarchy;
}
protected boolean calculateHasRootElementInHierarchy() {
if (this.getXmlRootElement() != null) {
return true;
}
for (JavaType jaxbType : getJaxbProject().getContextRoot().getJavaTypes()) {
if (jaxbType.getMapping() != null
&& ! jaxbType.getMapping().isXmlTransient()
&& jaxbType.getMapping().getXmlRootElement() != null
&& TypeTools.isSubType(
jaxbType.getTypeName().getFullyQualifiedName(), getJavaType().getTypeName().getFullyQualifiedName(), getJaxbProject().getJavaProject())) {
return true;
}
}
return false;
}
// ***** misc *****
@Override
protected Iterable<String> getTransientReferencedXmlTypeNames() {
return IterableTools.concatenate(
super.getTransientReferencedXmlTypeNames(),
new SingleElementIterable(getJavaResourceType().getSuperclassQualifiedName()));
}
@Override
protected Iterable<String> getNonTransientReferencedXmlTypeNames() {
return IterableTools.concatenate(
super.getNonTransientReferencedXmlTypeNames(),
IterableTools.singletonIterable(this.superclassName),
IterableTools.children(getAttributeMappings(), JaxbAttributeMapping.REFERENCED_XML_TYPE_NAMES_TRANSFORMER));
}
public JaxbAttributeMapping getXmlIdMapping() {
Iterator<XmlNamedNodeMapping> allXmlIdMappings =
IterableTools.filter(
IterableTools.<JaxbAttributeMapping, XmlNamedNodeMapping>downCast(
IterableTools.filter(
IterableTools.transform(
getAllAttributes(),
JaxbPersistentAttribute.MAPPING_TRANSFORMER),
XmlNamedNodeMapping.IS_NAMED_NODE_MAPPING)),
XmlNamedNodeMapping.HAS_XML_ID).iterator();
return allXmlIdMappings.hasNext() ? allXmlIdMappings.next() : null;
}
protected Iterable<? extends JaxbAttributeMapping> getAttributeMappings() {
return IterableTools.transform(getAttributes(), JaxbPersistentAttribute.MAPPING_TRANSFORMER);
}
// ***** content assist *****
@Override
public Iterable<String> getCompletionProposals(int pos) {
Iterable<String> result = super.getCompletionProposals(pos);
if (! IterableTools.isEmpty(result)) {
return result;
}
if (propTouches(pos)) {
return getPropProposals();
}
// TODO - factory methods?
for (JaxbPersistentAttribute attribute : this.getAttributes()) {
result = attribute.getCompletionProposals(pos);
if (!IterableTools.isEmpty(result)) {
return result;
}
}
return EmptyIterable.instance();
}
protected Iterable<String> getPropProposals() {
return IterableTools.transform(
IterableTools.transform(
getAllLocallyDefinedAttributes(),
JaxbPersistentAttribute.NAME_TRANSFORMER),
StringTools.JAVA_STRING_LITERAL_CONTENT_TRANSFORMER);
}
// ***** validation *****
@Override
public void validate(List<IMessage> messages, IReporter reporter) {
super.validate(messages, reporter);
validateConstructor(messages, reporter);
validatePropOrder(messages, reporter);
validateXmlAnyAttributeMapping(messages);
validateXmlAnyElementMapping(messages);
validateXmlValueMapping(messages);
validateXmlIDs(messages);
for (JaxbPersistentAttribute attribute : getAttributes()) {
attribute.validate(messages, reporter);
}
}
protected void validateConstructor(List<IMessage> messages, IReporter reporter) {
// TODO - factory class/method
if (! JAXB.XML_TYPE__DEFAULT_FACTORY_CLASS.equals(getFactoryClass())) {
if (StringTools.isBlank(getFactoryMethod())) {
messages.add(
this.buildValidationMessage(
getFactoryClassTextRange(),
JptJaxbCoreValidationMessages.XML_TYPE__UNSPECIFIED_FACTORY_METHOD
));
}
}
else {
if (getFactoryMethod() == null
&& getJavaType().getXmlJavaTypeAdapter() == null
&& ! getJavaResourceType().hasPublicOrProtectedNoArgConstructor()) {
messages.add(
this.buildValidationMessage(
getValidationTextRange(),
JptJaxbCoreValidationMessages.XML_TYPE__NO_PUBLIC_OR_PROTECTED_CONSTRUCTOR
));
}
}
}
protected void validatePropOrder(List<IMessage> messages, IReporter reporter) {
if (IterableTools.isEmpty(getPropOrder())) {
return;
}
// no duplicates
// all attributes/included attributes with XmlElement/s/Ref/s must be listed
// no nonexistent attributes (attributes mapped otherwise allowed) ...
// *except* no transient attributes allowed
Bag<String> props = CollectionTools.bag(getPropOrder());
Set<String> allAttributes = new HashSet<String>();
Set<String> requiredAttributes = new HashSet<String>();
Set<String> transientAttributes = new HashSet<String>();
for (JaxbPersistentAttribute attribute : getAllLocallyDefinedAttributes()) {
allAttributes.add(attribute.getName());
transientAttributes.add(attribute.getName());
}
for (JaxbPersistentAttribute attribute : getAllLocallyDefinedAttributes()) {
if (attribute.getMapping().isParticleMapping()) {
requiredAttributes.add(attribute.getName());
}
if (! attribute.getMapping().isTransient()) {
// remove transients (rather than previous algorithm of adding them)
// there may be two attributes of the same name (one field, one property) in
// a class, which is a correct configuration. we want to know if *every* attribute
// of a given name is transient (or if there's a single non-transient attribute)
transientAttributes.remove(attribute.getName());
}
}
Set<Integer> duplicateProps = new HashSet<Integer>();
Set<String> missingProps = new HashSet<String>(requiredAttributes);
Set<Integer> nonexistentProps = new HashSet<Integer>();
Set<Integer> transientProps = new HashSet<Integer>();
for (int i = 0; i < getPropOrderSize(); i ++ ) {
String prop = getProp(i);
if (props.count(prop) > 1) {
duplicateProps.add(i);
}
if (missingProps.contains(prop)) {
missingProps.remove(prop);
}
if (! allAttributes.contains(prop)) {
nonexistentProps.add(i);
}
if (transientAttributes.contains(prop)) {
transientProps.add(i);
}
}
for (int i : duplicateProps) {
messages.add(
this.buildValidationMessage(
getPropTextRange(i),
JptJaxbCoreValidationMessages.XML_TYPE__DUPLICATE_PROP,
getProp(i)));
}
for (String missingProp : missingProps) {
messages.add(
this.buildValidationMessage(
getPropOrderTextRange(),
JptJaxbCoreValidationMessages.XML_TYPE__MISSING_PROP,
missingProp));
}
for (int i : nonexistentProps) {
messages.add(
this.buildValidationMessage(
getPropTextRange(i),
JptJaxbCoreValidationMessages.XML_TYPE__NONEXISTENT_PROP,
getProp(i)));
}
for (int i : transientProps) {
messages.add(
this.buildValidationMessage(
getPropTextRange(i),
JptJaxbCoreValidationMessages.XML_TYPE__TRANSIENT_PROP,
getProp(i)));
}
}
protected void validateXmlAnyAttributeMapping(List<IMessage> messages) {
Set<JaxbPersistentAttribute> localAttributes = new HashSet<JaxbPersistentAttribute>();
Set<JaxbPersistentAttribute> allAttributes = new HashSet<JaxbPersistentAttribute>();
for (JaxbPersistentAttribute attribute : getAttributes()) {
if (attribute.getMappingKey() == MappingKeys.XML_ANY_ATTRIBUTE_ATTRIBUTE_MAPPING_KEY) {
localAttributes.add(attribute);
allAttributes.add(attribute);
}
}
for (JaxbPersistentAttribute attribute : getInheritedAttributes()) {
if (attribute.getMappingKey() == MappingKeys.XML_ANY_ATTRIBUTE_ATTRIBUTE_MAPPING_KEY) {
allAttributes.add(attribute);
}
}
if (allAttributes.size() > 1) {
messages.add(
this.buildValidationMessage(
getValidationTextRange(),
JptJaxbCoreValidationMessages.XML_ANY_ATTRIBUTE__MULTIPLE_MAPPINGS_DEFINED
));
for (JaxbPersistentAttribute anyAttribute : localAttributes) {
messages.add(
this.buildValidationMessage(
anyAttribute.getMapping(),
anyAttribute.getMapping().getValidationTextRange(),
JptJaxbCoreValidationMessages.XML_ANY_ATTRIBUTE__MULTIPLE_MAPPINGS_DEFINED
));
}
}
}
protected void validateXmlAnyElementMapping(List<IMessage> messages) {
Set<JaxbPersistentAttribute> localAttributes = new HashSet<JaxbPersistentAttribute>();
Set<JaxbPersistentAttribute> allAttributes = new HashSet<JaxbPersistentAttribute>();
for (JaxbPersistentAttribute attribute : getAttributes()) {
if (attribute.getMappingKey() == MappingKeys.XML_ANY_ELEMENT_ATTRIBUTE_MAPPING_KEY) {
localAttributes.add(attribute);
allAttributes.add(attribute);
}
}
for (JaxbPersistentAttribute attribute : getInheritedAttributes()) {
if (attribute.getMappingKey() == MappingKeys.XML_ANY_ELEMENT_ATTRIBUTE_MAPPING_KEY) {
allAttributes.add(attribute);
}
}
if (allAttributes.size() > 1) {
messages.add(
this.buildValidationMessage(
getValidationTextRange(),
JptJaxbCoreValidationMessages.XML_ANY_ELEMENT__MULTIPLE_MAPPINGS_DEFINED
));
for (JaxbPersistentAttribute anyAttribute : localAttributes) {
messages.add(
this.buildValidationMessage(
anyAttribute.getMapping(),
anyAttribute.getMapping().getValidationTextRange(),
JptJaxbCoreValidationMessages.XML_ANY_ELEMENT__MULTIPLE_MAPPINGS_DEFINED
));
}
}
}
protected void validateXmlValueMapping(List<IMessage> messages) {
Set<JaxbPersistentAttribute> localAttributes = new HashSet<JaxbPersistentAttribute>();
Set<JaxbPersistentAttribute> allAttributes = new HashSet<JaxbPersistentAttribute>();
for (JaxbPersistentAttribute attribute : getAttributes()) {
if (attribute.getMappingKey() == MappingKeys.XML_VALUE_ATTRIBUTE_MAPPING_KEY) {
localAttributes.add(attribute);
allAttributes.add(attribute);
}
}
for (JaxbPersistentAttribute attribute : getInheritedAttributes()) {
if (attribute.getMappingKey() == MappingKeys.XML_VALUE_ATTRIBUTE_MAPPING_KEY) {
allAttributes.add(attribute);
}
}
if (allAttributes.size() > 1) {
messages.add(
this.buildValidationMessage(
getValidationTextRange(),
JptJaxbCoreValidationMessages.XML_VALUE__MULTIPLE_MAPPINGS_DEFINED
));
for (JaxbPersistentAttribute anyAttribute : localAttributes) {
messages.add(
this.buildValidationMessage(
anyAttribute.getMapping(),
anyAttribute.getMapping().getValidationTextRange(),
JptJaxbCoreValidationMessages.XML_VALUE__MULTIPLE_MAPPINGS_DEFINED
));
}
}
}
protected void validateXmlIDs(List<IMessage> messages) {
Set<JaxbPersistentAttribute> localAttributes = new HashSet<JaxbPersistentAttribute>();
Set<JaxbPersistentAttribute> allAttributes = new HashSet<JaxbPersistentAttribute>();
for (JaxbPersistentAttribute attribute : getAttributes()) {
if ((attribute.getMappingKey() == MappingKeys.XML_ATTRIBUTE_ATTRIBUTE_MAPPING_KEY
|| attribute.getMappingKey() == MappingKeys.XML_ELEMENT_ATTRIBUTE_MAPPING_KEY)
&& ((XmlNamedNodeMapping) attribute.getMapping()).getXmlID() != null) {
localAttributes.add(attribute);
allAttributes.add(attribute);
}
}
for (JaxbPersistentAttribute attribute : getInheritedAttributes()) {
if ((attribute.getMappingKey() == MappingKeys.XML_ATTRIBUTE_ATTRIBUTE_MAPPING_KEY
|| attribute.getMappingKey() == MappingKeys.XML_ELEMENT_ATTRIBUTE_MAPPING_KEY)
&& ((XmlNamedNodeMapping) attribute.getMapping()).getXmlID() != null) {
allAttributes.add(attribute);
}
}
if (allAttributes.size() > 1) {
messages.add(
this.buildValidationMessage(
getValidationTextRange(),
JptJaxbCoreValidationMessages.XML_ID__MULTIPLE_MAPPINGS_DEFINED
));
for (JaxbPersistentAttribute anyAttribute : localAttributes) {
messages.add(
this.buildValidationMessage(
anyAttribute.getMapping(),
anyAttribute.getMapping().getValidationTextRange(),
JptJaxbCoreValidationMessages.XML_ID__MULTIPLE_MAPPINGS_DEFINED
));
}
}
}
protected TextRange getFactoryClassTextRange() {
TextRange result = getXmlTypeAnnotation().getFactoryClassTextRange();
return (result != null) ? result : getValidationTextRange();
}
protected TextRange getFactoryMethodTextRange() {
TextRange result = getXmlTypeAnnotation().getFactoryMethodTextRange();
return (result != null) ? result : getValidationTextRange();
}
protected TextRange getPropOrderTextRange() {
TextRange result = getXmlTypeAnnotation().getPropOrderTextRange();
return (result != null) ? result : getValidationTextRange();
}
protected TextRange getPropTextRange(int index) {
return getXmlTypeAnnotation().getPropTextRange(index);
}
protected boolean propTouches(int pos) {
if (getXmlTypeAnnotation().propOrderTouches(pos)) {
for (int i = 0; i < getXmlTypeAnnotation().getPropOrderSize(); i ++ ) {
if (getXmlTypeAnnotation().propTouches(i, pos)) {
return true;
}
}
}
return false;
}
/**
* xml prop order container
*/
protected class PropOrderContainer
extends ListContainer<String, String> {
@Override
protected String getContextElementsPropertyName() {
return PROP_ORDER_LIST;
}
@Override
protected String buildContextElement(String resourceElement) {
return resourceElement;
}
@Override
protected ListIterable<String> getResourceElements() {
return GenericJavaClassMapping.this.getResourcePropOrder();
}
@Override
protected String getResourceElement(String contextElement) {
return contextElement;
}
}
}