blob: 30906192bbff152272291a31cbae8a41e1ebb1f7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 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.common.utility.internal.iterables.ListIterable;
import org.eclipse.jpt.jaxb.core.context.JaxbContextRoot;
import org.eclipse.jpt.jaxb.core.context.JaxbPackage;
import org.eclipse.jpt.jaxb.core.context.JaxbPackageInfo;
import org.eclipse.jpt.jaxb.core.context.JaxbPersistentType;
import org.eclipse.jpt.jaxb.core.context.JaxbQName;
import org.eclipse.jpt.jaxb.core.context.XmlRootElement;
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.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 AbstractJavaPersistentType
extends AbstractJavaType
implements JaxbPersistentType {
protected final JaxbQName qName;
protected String factoryClass;
protected String factoryMethod;
protected final PropOrderContainer propOrderContainer;
protected XmlRootElement rootElement;
public AbstractJavaPersistentType(JaxbContextRoot parent, JavaResourceAbstractType resourceType) {
super(parent, resourceType);
this.qName = buildQName();
this.factoryClass = this.getResourceFactoryClass();
this.factoryMethod = this.getResourceFactoryMethod();
this.propOrderContainer = new PropOrderContainer();
this.rootElement = this.buildRootElement();
}
protected JaxbQName buildQName() {
return new XmlTypeQName(this);
}
@Override
public JaxbContextRoot getParent() {
return (JaxbContextRoot) super.getParent();
}
protected JaxbPackageInfo getPackageInfo() {
JaxbPackage jaxbPackage = getParent().getPackage(this.getPackageName());
return jaxbPackage == null ? null : jaxbPackage.getPackageInfo();
}
// ********** synchronize/update **********
@Override
public void synchronizeWithResourceModel() {
super.synchronizeWithResourceModel();
this.qName.synchronizeWithResourceModel();
this.setFactoryClass_(getResourceFactoryClass());
this.setFactoryMethod_(getResourceFactoryMethod());
this.syncPropOrder();
this.syncRootElement();
}
@Override
public void update() {
super.update();
this.qName.update();
}
// ********** xml type annotation **********
protected XmlTypeAnnotation getXmlTypeAnnotation() {
return (XmlTypeAnnotation) this.getJavaResourceType().getNonNullAnnotation(JAXB.XML_TYPE);
}
// ***** schema type ref *****
public JaxbQName getQName() {
return this.qName;
}
// ********** factory class **********
public String getFactoryClass() {
return this.factoryClass;
}
public void setFactoryClass(String factoryClass) {
this.getXmlTypeAnnotation().setFactoryClass(factoryClass);
this.setFactoryClass_(factoryClass);
}
protected void setFactoryClass_(String factoryClass) {
String old = this.factoryClass;
this.factoryClass = factoryClass;
this.firePropertyChanged(FACTORY_CLASS_PROPERTY, old, factoryClass);
}
protected String getResourceFactoryClass() {
return this.getXmlTypeAnnotation().getFactoryClass();
}
// ********** factory method **********
public String getFactoryMethod() {
return this.factoryMethod;
}
public void setFactoryMethod(String factoryMethod) {
this.getXmlTypeAnnotation().setFactoryMethod(factoryMethod);
this.setFactoryMethod_(factoryMethod);
}
protected void setFactoryMethod_(String factoryMethod) {
String old = this.factoryMethod;
this.factoryMethod = factoryMethod;
this.firePropertyChanged(FACTORY_METHOD_PROPERTY, old, factoryMethod);
}
protected String getResourceFactoryMethod() {
return this.getXmlTypeAnnotation().getFactoryMethod();
}
// ********** prop order **********
public ListIterable<String> getPropOrder() {
return this.propOrderContainer.getContextElements();
}
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 syncPropOrder() {
this.propOrderContainer.synchronizeWithResourceModel();
}
protected ListIterable<String> getResourcePropOrder() {
return this.getXmlTypeAnnotation().getPropOrder();
}
// *************** root element *********************
public XmlRootElement getRootElement() {
return this.rootElement;
}
public boolean isRootElement() {
return this.rootElement != null;
}
public XmlRootElement setRootElement(String name) {
if (name == null) {
this.getJavaResourceType().removeAnnotation(JAXB.XML_ROOT_ELEMENT);
this.setRootElement_(null);
return null;
}
XmlRootElementAnnotation resourceRootElement = (XmlRootElementAnnotation) getJavaResourceType().addAnnotation(JAXB.XML_ROOT_ELEMENT);
resourceRootElement.setName(name);
XmlRootElement contextRootElement = this.buildRootElement(resourceRootElement);
this.setRootElement_(contextRootElement);
return contextRootElement;
}
protected void setRootElement_(XmlRootElement rootElement) {
XmlRootElement old = this.rootElement;
this.rootElement = rootElement;
this.firePropertyChanged(ROOT_ELEMENT, old, rootElement);
}
protected XmlRootElement buildRootElement() {
XmlRootElementAnnotation resourceRootElement = this.getRootElementAnnotation();
return resourceRootElement == null ? null : this.buildRootElement(resourceRootElement);
}
protected XmlRootElement buildRootElement(XmlRootElementAnnotation resourceRootElement) {
return getFactory().buildJavaXmlRootElement(this, resourceRootElement);
}
protected void syncRootElement() {
XmlRootElementAnnotation resourceRootElement = this.getRootElementAnnotation();
if (resourceRootElement != null) {
if (this.rootElement != null) {
this.rootElement.synchronizeWithResourceModel();
}
else {
this.setRootElement_(this.buildRootElement(resourceRootElement));
}
}
else if (this.rootElement != null) {
this.setRootElement_(null);
}
}
protected XmlRootElementAnnotation getRootElementAnnotation() {
return (XmlRootElementAnnotation) this.getJavaResourceType().getAnnotation(JAXB.XML_ROOT_ELEMENT);
}
// **************** content assist ****************************************
@Override
public Iterable<String> getJavaCompletionProposals(
int pos, Filter<String> filter, CompilationUnit astRoot) {
getJaxbProject().getSchemaLibrary().refreshSchema(getJaxbPackage().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.rootElement != null) {
result = this.rootElement.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 : super.getValidationTextRange(astRoot);
}
@Override
public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
super.validate(messages, reporter, astRoot);
this.qName.validate(messages, reporter, astRoot);
if (this.rootElement != null) {
this.rootElement.validate(messages, reporter, astRoot);
}
}
// **************** misc **************************************************
public XsdTypeDefinition getXsdTypeDefinition() {
XsdSchema xsdSchema = getJaxbPackage().getXsdSchema();
if (xsdSchema == null) {
return null;
}
if (! StringTools.stringIsEmpty(this.qName.getName())) {
return xsdSchema.getTypeDefinition(this.qName.getNamespace(), this.qName.getName());
}
if (this.rootElement != null) {
XsdElementDeclaration xsdElement = xsdSchema.getElementDeclaration(this.rootElement.getQName().getNamespace(), this.rootElement.getQName().getName());
if (xsdElement != null) {
return xsdElement.getType();
}
}
return null;
}
@Override
public void toString(StringBuilder sb) {
super.toString(sb);
sb.append(this.getFullyQualifiedName());
}
protected class XmlTypeQName
extends AbstractJavaQName {
protected XmlTypeQName(JavaContextNode parent) {
super(parent, new QNameAnnotationProxy());
}
@Override
public String getDefaultNamespace() {
return AbstractJavaPersistentType.this.getJaxbPackage().getNamespace();
}
@Override
public String getDefaultName() {
return Introspector.decapitalize(AbstractJavaPersistentType.this.getSimpleName());
}
@Override
protected Iterable<String> getNamespaceProposals(Filter<String> filter) {
XsdSchema schema = AbstractJavaPersistentType.this.getJaxbPackage().getXsdSchema();
if (schema == null) {
return EmptyIterable.instance();
}
return schema.getNamespaceProposals(filter);
}
@Override
protected Iterable<String> getNameProposals(Filter<String> filter) {
XsdSchema schema = AbstractJavaPersistentType.this.getJaxbPackage().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(),
AbstractJavaPersistentType.this.getJaxbPackage().getNamespace())) {
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 = AbstractJavaPersistentType.this.getJaxbPackage().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 AbstractJavaPersistentType.this.getXmlTypeAnnotation();
}
}
/**
* 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 AbstractJavaPersistentType.this.getResourcePropOrder();
}
@Override
protected String getResourceElement(String contextElement) {
return contextElement;
}
}
}