blob: 37e03e20aaa7d0c264c8360f9ccecf7aa4ae0249 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 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.beans.Introspector;
import java.util.List;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jpt.common.core.resource.java.JavaResourceAbstractType;
import org.eclipse.jpt.common.core.utility.TextRange;
import org.eclipse.jpt.common.utility.Filter;
import org.eclipse.jpt.common.utility.internal.CollectionTools;
import org.eclipse.jpt.common.utility.internal.StringTools;
import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable;
import org.eclipse.jpt.jaxb.core.context.JaxbPackage;
import org.eclipse.jpt.jaxb.core.context.JaxbQName;
import org.eclipse.jpt.jaxb.core.context.JaxbType;
import org.eclipse.jpt.jaxb.core.context.JaxbTypeMapping;
import org.eclipse.jpt.jaxb.core.context.XmlRootElement;
import org.eclipse.jpt.jaxb.core.context.XmlSeeAlso;
import org.eclipse.jpt.jaxb.core.context.java.JavaContextNode;
import org.eclipse.jpt.jaxb.core.internal.JptJaxbCoreMessages;
import org.eclipse.jpt.jaxb.core.internal.validation.DefaultValidationMessages;
import org.eclipse.jpt.jaxb.core.internal.validation.JaxbValidationMessages;
import org.eclipse.jpt.jaxb.core.resource.java.JAXB;
import org.eclipse.jpt.jaxb.core.resource.java.QNameAnnotation;
import org.eclipse.jpt.jaxb.core.resource.java.XmlRootElementAnnotation;
import org.eclipse.jpt.jaxb.core.resource.java.XmlSeeAlsoAnnotation;
import org.eclipse.jpt.jaxb.core.resource.java.XmlTransientAnnotation;
import org.eclipse.jpt.jaxb.core.resource.java.XmlTypeAnnotation;
import org.eclipse.jpt.jaxb.core.xsd.XsdElementDeclaration;
import org.eclipse.jpt.jaxb.core.xsd.XsdSchema;
import org.eclipse.jpt.jaxb.core.xsd.XsdTypeDefinition;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
public abstract class AbstractJavaTypeMapping
extends AbstractJavaContextNode
implements JaxbTypeMapping {
protected boolean xmlTransient;
protected final JaxbQName qName;
protected XmlRootElement xmlRootElement;
protected XmlSeeAlso xmlSeeAlso;
protected AbstractJavaTypeMapping(JaxbType parent) {
super(parent);
initXmlTransient();
this.qName = buildQName();
initXmlRootElement();
initializeXmlSeeAlso();
}
public JaxbType getJaxbType() {
return (JaxbType) getParent();
}
protected JavaResourceAbstractType getJavaResourceType() {
return getJaxbType().getJavaResourceType();
}
protected JaxbPackage getJaxbPackage() {
return getJaxbType().getJaxbPackage();
}
// ***** sync/update *****
@Override
public void synchronizeWithResourceModel() {
super.synchronizeWithResourceModel();
syncXmlTransient();
this.qName.synchronizeWithResourceModel();
syncXmlRootElement();
syncXmlSeeAlso();
}
@Override
public void update() {
super.update();
this.qName.update();
updateXmlRootElement();
updateXmlSeeAlso();
}
// ***** XmlTransient *****
public boolean isXmlTransient() {
return this.xmlTransient;
}
public void setXmlTransient(boolean newValue) {
getJavaResourceType().addAnnotation(JAXB.XML_TRANSIENT);
setXmlTransient_(newValue);
}
protected void setXmlTransient_(boolean newValue) {
boolean old = this.xmlTransient;
this.xmlTransient = newValue;
firePropertyChanged(XML_TRANSIENT_PROPERTY, old, newValue);
}
protected XmlTransientAnnotation getXmlTransientAnnotation() {
return (XmlTransientAnnotation) getJavaResourceType().getAnnotation(JAXB.XML_TRANSIENT);
}
protected void initXmlTransient() {
this.xmlTransient = getXmlTransientAnnotation() != null;
}
protected void syncXmlTransient() {
setXmlTransient_(getXmlTransientAnnotation() != null);
}
// ***** XmlType.name and namespace *****
public JaxbQName getQName() {
return this.qName;
}
protected JaxbQName buildQName() {
return new XmlTypeQName(this);
}
protected XmlTypeAnnotation getXmlTypeAnnotation() {
return (XmlTypeAnnotation) getJavaResourceType().getNonNullAnnotation(JAXB.XML_TYPE);
}
// ***** XmlRootElement *****
public XmlRootElement getXmlRootElement() {
return this.xmlRootElement;
}
protected void setXmlRootElement_(XmlRootElement rootElement) {
XmlRootElement old = this.xmlRootElement;
this.xmlRootElement = rootElement;
this.firePropertyChanged(XML_ROOT_ELEMENT_PROPERTY, old, rootElement);
}
public XmlRootElement addXmlRootElement() {
if (this.xmlRootElement != null) {
throw new IllegalStateException();
}
XmlRootElementAnnotation annotation
= (XmlRootElementAnnotation) getJavaResourceType().addAnnotation(JAXB.XML_ROOT_ELEMENT);
XmlRootElement xmlRootElement = buildXmlRootElement(annotation);
setXmlRootElement_(xmlRootElement);
return xmlRootElement;
}
public void removeXmlRootElement() {
if (this.xmlRootElement == null) {
throw new IllegalStateException();
}
getJavaResourceType().removeAnnotation(JAXB.XML_ROOT_ELEMENT);
setXmlRootElement_(null);
}
protected XmlRootElementAnnotation getXmlRootElementAnnotation() {
return (XmlRootElementAnnotation) getJavaResourceType().getAnnotation(JAXB.XML_ROOT_ELEMENT);
}
protected XmlRootElement buildXmlRootElement() {
XmlRootElementAnnotation annotation = getXmlRootElementAnnotation();
return annotation == null ? null : buildXmlRootElement(annotation);
}
protected XmlRootElement buildXmlRootElement(XmlRootElementAnnotation resourceRootElement) {
return getFactory().buildJavaXmlRootElement(this, resourceRootElement);
}
protected void initXmlRootElement() {
this.xmlRootElement = this.buildXmlRootElement();
}
protected void syncXmlRootElement() {
XmlRootElementAnnotation annotation = getXmlRootElementAnnotation();
if (annotation != null) {
if (this.xmlRootElement != null) {
this.xmlRootElement.synchronizeWithResourceModel();
}
else {
setXmlRootElement_(buildXmlRootElement(annotation));
}
}
else if (this.xmlRootElement != null) {
setXmlRootElement_(null);
}
}
protected void updateXmlRootElement() {
if (this.xmlRootElement != null) {
this.xmlRootElement.update();
}
}
// ***** XmlSeeAlso *****
public XmlSeeAlso getXmlSeeAlso() {
return this.xmlSeeAlso;
}
protected void setXmlSeeAlso_(XmlSeeAlso xmlSeeAlso) {
XmlSeeAlso old = this.xmlSeeAlso;
this.xmlSeeAlso = xmlSeeAlso;
firePropertyChanged(XML_SEE_ALSO_PROPERTY, old, xmlSeeAlso);
}
public XmlSeeAlso addXmlSeeAlso() {
if (this.xmlSeeAlso != null) {
throw new IllegalStateException();
}
XmlSeeAlsoAnnotation annotation
= (XmlSeeAlsoAnnotation) getJavaResourceType().addAnnotation(JAXB.XML_SEE_ALSO);
XmlSeeAlso xmlSeeAlso = buildXmlSeeAlso(annotation);
setXmlSeeAlso_(xmlSeeAlso);
return xmlSeeAlso;
}
public void removeXmlSeeAlso() {
if (this.xmlSeeAlso == null) {
throw new IllegalStateException();
}
getJavaResourceType().removeAnnotation(JAXB.XML_SEE_ALSO);
setXmlSeeAlso_(null);
}
protected XmlSeeAlsoAnnotation getXmlSeeAlsoAnnotation() {
return (XmlSeeAlsoAnnotation) getJavaResourceType().getAnnotation(JAXB.XML_SEE_ALSO);
}
protected XmlSeeAlso buildXmlSeeAlso(XmlSeeAlsoAnnotation annotation) {
return new GenericJavaXmlSeeAlso(this, annotation);
}
protected void initializeXmlSeeAlso() {
XmlSeeAlsoAnnotation annotation = getXmlSeeAlsoAnnotation();
this.xmlSeeAlso = (annotation == null) ?
null
: buildXmlSeeAlso(annotation);
}
protected void syncXmlSeeAlso() {
XmlSeeAlsoAnnotation annotation = getXmlSeeAlsoAnnotation();
if (annotation != null) {
if (this.xmlSeeAlso != null) {
this.xmlSeeAlso.synchronizeWithResourceModel();
}
else {
setXmlSeeAlso_(buildXmlSeeAlso(annotation));
}
}
else {
setXmlSeeAlso_(null);
}
}
protected void updateXmlSeeAlso() {
if (this.xmlSeeAlso != null) {
this.xmlSeeAlso.update();
}
}
// ***** misc *****
public final Iterable<String> getReferencedXmlTypeNames() {
return (this.xmlTransient) ?
getTransientReferencedXmlTypeNames()
: getNonTransientReferencedXmlTypeNames();
}
protected Iterable<String> getTransientReferencedXmlTypeNames() {
return EmptyIterable.instance();
}
protected Iterable<String> getNonTransientReferencedXmlTypeNames() {
if (this.xmlSeeAlso != null) {
return this.xmlSeeAlso.getReferencedXmlTypeNames();
}
return EmptyIterable.instance();
}
// ***** content assist *****
@Override
public Iterable<String> getJavaCompletionProposals(
int pos, Filter<String> filter, CompilationUnit astRoot) {
JaxbPackage jaxbPackage = getJaxbPackage();
if (jaxbPackage != null) {
getJaxbProject().getSchemaLibrary().refreshSchema(jaxbPackage.getNamespace());
}
Iterable<String> result = super.getJavaCompletionProposals(pos, filter, astRoot);
if (! CollectionTools.isEmpty(result)) {
return result;
}
result = this.qName.getJavaCompletionProposals(pos, filter, astRoot);
if (! CollectionTools.isEmpty(result)) {
return result;
}
if (this.xmlRootElement != null) {
result = this.xmlRootElement.getJavaCompletionProposals(pos, filter, astRoot);
if (! CollectionTools.isEmpty(result)) {
return result;
}
}
return EmptyIterable.instance();
}
// ***** validation *****
@Override
public TextRange getValidationTextRange(CompilationUnit astRoot) {
TextRange textRange = getXmlTypeAnnotation().getTextRange(astRoot);
return (textRange != null) ? textRange : getJaxbType().getValidationTextRange(astRoot);
}
@Override
public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
super.validate(messages, reporter, astRoot);
if (! this.xmlTransient) {
this.qName.validate(messages, reporter, astRoot);
if (this.xmlRootElement != null) {
this.xmlRootElement.validate(messages, reporter, astRoot);
}
}
}
// ***** misc *****
public XsdTypeDefinition getXsdTypeDefinition() {
JaxbPackage jaxbPackage = getJaxbPackage();
XsdSchema xsdSchema = (jaxbPackage == null) ? null : jaxbPackage.getXsdSchema();
if (xsdSchema == null) {
return null;
}
if (! StringTools.stringIsEmpty(this.qName.getName())) {
return xsdSchema.getTypeDefinition(this.qName.getNamespace(), this.qName.getName());
}
if (this.xmlRootElement != null) {
XsdElementDeclaration xsdElement
= xsdSchema.getElementDeclaration(
this.xmlRootElement.getQName().getNamespace(),
this.xmlRootElement.getQName().getName());
if (xsdElement != null) {
return xsdElement.getType();
}
}
return null;
}
public boolean hasRootElementInHierarchy() {
return this.xmlRootElement != null;
}
protected class XmlTypeQName
extends AbstractJavaQName {
protected XmlTypeQName(JavaContextNode parent) {
super(parent, new QNameAnnotationProxy());
}
@Override
protected JaxbPackage getJaxbPackage() {
return AbstractJavaTypeMapping.this.getJaxbType().getJaxbPackage();
}
@Override
public String getDefaultNamespace() {
JaxbPackage jaxbPackage = AbstractJavaTypeMapping.this.getJaxbType().getJaxbPackage();
return (jaxbPackage == null) ? null : jaxbPackage.getNamespace();
}
@Override
public String getDefaultName() {
return Introspector.decapitalize(AbstractJavaTypeMapping.this.getJaxbType().getSimpleName());
}
@Override
protected Iterable<String> getNamespaceProposals(Filter<String> filter) {
XsdSchema schema = this.getXsdSchema();
if (schema == null) {
return EmptyIterable.instance();
}
return schema.getNamespaceProposals(filter);
}
@Override
protected Iterable<String> getNameProposals(Filter<String> filter) {
XsdSchema schema = this.getXsdSchema();
if (schema == null) {
return EmptyIterable.instance();
}
return schema.getTypeNameProposals(getNamespace(), filter);
}
@Override
public String getReferencedComponentTypeDescription() {
return JptJaxbCoreMessages.XML_TYPE_DESC;
}
@Override
protected void validateName(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
// do not call super... - it is not an error if the name is ""
// if name is absent (""), namespace cannot be different from package namespace
if ("".equals(getName())
&& ! StringTools.stringsAreEqual(
getNamespace(),
getDefaultNamespace())) {
messages.add(
DefaultValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
JaxbValidationMessages.XML_TYPE__UNMATCHING_NAMESPACE_FOR_ANONYMOUS_TYPE,
this,
getXmlTypeAnnotation().getNamespaceTextRange(astRoot)));
}
}
@Override
protected void validateReference(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
// if name is not absent (""), type must be from schema associated with this package
String name = getName();
String namespace = getNamespace();
if (! StringTools.stringIsEmpty(name)) {
XsdSchema schema = this.getXsdSchema();
if (schema != null) {
XsdTypeDefinition schemaType = schema.getTypeDefinition(namespace, name);
if (schemaType == null) {
messages.add(getUnresolveSchemaComponentMessage(astRoot));
}
}
}
}
}
protected class QNameAnnotationProxy
extends AbstractJavaQName.AbstractQNameAnnotationProxy {
@Override
protected QNameAnnotation getAnnotation(boolean createIfNull) {
return AbstractJavaTypeMapping.this.getXmlTypeAnnotation();
}
}
}