| /******************************************************************************* |
| * Copyright (c) 2012 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.eclipselink.core.internal.context.java; |
| |
| import java.util.List; |
| import org.eclipse.jdt.core.dom.CompilationUnit; |
| 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.CompositeIterable; |
| import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable; |
| import org.eclipse.jpt.jaxb.core.JaxbNode; |
| import org.eclipse.jpt.jaxb.core.context.JaxbClassMapping; |
| import org.eclipse.jpt.jaxb.core.context.JaxbPackage; |
| import org.eclipse.jpt.jaxb.core.context.java.JavaContextNode; |
| import org.eclipse.jpt.jaxb.core.internal.context.java.AbstractJavaContextNode; |
| import org.eclipse.jpt.jaxb.core.xsd.XsdTypeDefinition; |
| import org.eclipse.jpt.jaxb.eclipselink.core.context.java.ELClassMapping; |
| import org.eclipse.jpt.jaxb.eclipselink.core.context.java.ELXmlJoinNode; |
| import org.eclipse.jpt.jaxb.eclipselink.core.context.java.ELXmlJoinNodesMapping; |
| import org.eclipse.jpt.jaxb.eclipselink.core.internal.context.xpath.java.XPath; |
| import org.eclipse.jpt.jaxb.eclipselink.core.internal.context.xpath.java.XPathFactory; |
| import org.eclipse.jpt.jaxb.eclipselink.core.internal.validation.ELJaxbValidationMessageBuilder; |
| import org.eclipse.jpt.jaxb.eclipselink.core.internal.validation.ELJaxbValidationMessages; |
| import org.eclipse.jpt.jaxb.eclipselink.core.resource.java.XmlJoinNodeAnnotation; |
| import org.eclipse.wst.validation.internal.provisional.core.IMessage; |
| import org.eclipse.wst.validation.internal.provisional.core.IReporter; |
| |
| |
| public class ELJavaXmlJoinNode |
| extends AbstractJavaContextNode |
| implements ELXmlJoinNode { |
| |
| protected String xmlPath; |
| |
| protected String referencedXmlPath; |
| |
| protected Context context; |
| |
| |
| public ELJavaXmlJoinNode(JavaContextNode parent, Context context) { |
| super(parent); |
| this.context = context; |
| initXmlPath(); |
| initReferencedXmlPath(); |
| } |
| |
| |
| protected JaxbPackage getJaxbPackage() { |
| return getClassMapping().getJaxbType().getJaxbPackage(); |
| } |
| |
| |
| // ***** sync/update ***** |
| |
| @Override |
| public void synchronizeWithResourceModel() { |
| super.synchronizeWithResourceModel(); |
| syncXmlPath(); |
| syncReferencedXmlPath(); |
| } |
| |
| |
| // ***** xmlPath ***** |
| |
| public String getXmlPath() { |
| return this.xmlPath; |
| } |
| |
| public void setXmlPath(String xmlPath) { |
| getAnnotation().setXmlPath(xmlPath); |
| setXmlPath_(xmlPath); |
| } |
| |
| protected void setXmlPath_(String xmlPath) { |
| String old = this.xmlPath; |
| this.xmlPath = xmlPath; |
| firePropertyChanged(XML_PATH_PROPERTY, old, this.xmlPath); |
| } |
| |
| protected void initXmlPath() { |
| this.xmlPath = getAnnotation().getXmlPath(); |
| } |
| |
| protected void syncXmlPath() { |
| setXmlPath_(getAnnotation().getXmlPath()); |
| } |
| |
| |
| // ***** referencedXmlPath ***** |
| |
| public String getReferencedXmlPath() { |
| return this.referencedXmlPath; |
| } |
| |
| public void setReferencedXmlPath(String referencedXmlPath) { |
| getAnnotation().setReferencedXmlPath(referencedXmlPath); |
| setReferencedXmlPath_(referencedXmlPath); |
| } |
| |
| protected void setReferencedXmlPath_(String referencedXmlPath) { |
| String old = this.referencedXmlPath; |
| this.referencedXmlPath = referencedXmlPath; |
| firePropertyChanged(REFERENCED_XML_PATH_PROPERTY, old, this.referencedXmlPath); |
| } |
| |
| protected void initReferencedXmlPath() { |
| this.referencedXmlPath = getAnnotation().getReferencedXmlPath(); |
| } |
| |
| protected void syncReferencedXmlPath() { |
| setReferencedXmlPath_(getAnnotation().getReferencedXmlPath()); |
| } |
| |
| |
| protected XmlJoinNodeAnnotation getAnnotation() { |
| return this.context.getAnnotation(); |
| } |
| |
| protected ELXmlJoinNodesMapping getAttributeMapping() { |
| return this.context.getAttributeMapping(); |
| } |
| |
| protected JaxbClassMapping getClassMapping() { |
| return getAttributeMapping().getClassMapping(); |
| } |
| |
| |
| // ***** content assist ***** |
| |
| @Override |
| public Iterable<String> getJavaCompletionProposals( |
| int pos, Filter<String> filter, CompilationUnit astRoot) { |
| |
| if (getAnnotation().xmlPathTouches(pos, astRoot) && this.xmlPath != null) { |
| XsdTypeDefinition xsdType = getClassMapping().getXsdTypeDefinition(); |
| XPath xpath = XPathFactory.instance().getXpath(this.xmlPath); |
| return xpath.getCompletionProposals(new XmlPathContext(astRoot), xsdType, pos, filter); |
| } |
| |
| if (getAnnotation().referencedXmlPathTouches(pos, astRoot) && this.referencedXmlPath != null) { |
| |
| |
| XsdTypeDefinition xsdType = getAttributeMapping().getReferencedXsdTypeDefinition(); |
| XPath xpath = XPathFactory.instance().getXpath(this.referencedXmlPath); |
| Iterable<String> result = xpath.getCompletionProposals(new ReferencedXmlPathContext(astRoot), xsdType, pos, filter); |
| |
| ELClassMapping referencedClassMapping = this.context.getAttributeMapping().getReferencedClassMapping(); |
| if (referencedClassMapping != null) { |
| result = new CompositeIterable<String>( |
| result, |
| StringTools.convertToJavaStringLiterals(referencedClassMapping.getKeyXPaths())); |
| } |
| |
| return CollectionTools.sortedSet(result); |
| } |
| |
| return EmptyIterable.instance(); |
| } |
| |
| |
| // ***** validation ***** |
| |
| @Override |
| public TextRange getValidationTextRange(CompilationUnit astRoot) { |
| return getAnnotation().getTextRange(astRoot); |
| } |
| |
| @Override |
| public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) { |
| super.validate(messages, reporter, astRoot); |
| |
| validateXmlPath(messages, astRoot); |
| validateReferencedXmlPath(messages, astRoot); |
| } |
| |
| protected void validateXmlPath(List<IMessage> messages, CompilationUnit astRoot) { |
| if (StringTools.stringIsEmpty(this.xmlPath)) { |
| messages.add( |
| ELJaxbValidationMessageBuilder.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| ELJaxbValidationMessages.XML_JOIN_NODE__XML_PATH_NOT_SPECIFIED, |
| ELJavaXmlJoinNode.this, |
| getXmlPathTextRange(astRoot))); |
| return; |
| } |
| |
| if (this.xmlPath.startsWith(XPath.DELIM)) { |
| messages.add( |
| ELJaxbValidationMessageBuilder.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| ELJaxbValidationMessages.XPATH__ROOT_NOT_SUPPORTED, |
| ELJavaXmlJoinNode.this, |
| getXmlPathTextRange(astRoot))); |
| return; |
| } |
| |
| XsdTypeDefinition xsdType = getClassMapping().getXsdTypeDefinition(); |
| XPath xpath = XPathFactory.instance().getXpath(this.xmlPath); |
| xpath.validate(new XmlPathContext(astRoot), xsdType, messages); |
| } |
| |
| protected void validateReferencedXmlPath(List<IMessage> messages, CompilationUnit astRoot) { |
| if (StringTools.stringIsEmpty(this.referencedXmlPath)) { |
| messages.add( |
| ELJaxbValidationMessageBuilder.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| ELJaxbValidationMessages.XML_JOIN_NODE__REFERENCED_XML_PATH_NOT_SPECIFIED, |
| ELJavaXmlJoinNode.this, |
| getReferencedXmlPathTextRange(astRoot))); |
| return; |
| } |
| |
| if (this.referencedXmlPath.startsWith(XPath.DELIM)) { |
| messages.add( |
| ELJaxbValidationMessageBuilder.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| ELJaxbValidationMessages.XPATH__ROOT_NOT_SUPPORTED, |
| ELJavaXmlJoinNode.this, |
| getReferencedXmlPathTextRange(astRoot))); |
| return; |
| } |
| |
| ELClassMapping referencedClassMapping = this.context.getAttributeMapping().getReferencedClassMapping(); |
| if (referencedClassMapping != null && |
| ! CollectionTools.contains(referencedClassMapping.getKeyXPaths(), this.referencedXmlPath)) { |
| messages.add( |
| ELJaxbValidationMessageBuilder.buildMessage( |
| IMessage.HIGH_SEVERITY, |
| ELJaxbValidationMessages.XML_JOIN_NODE__REFERENCED_XML_PATH_NOT_IN_REFERENCED_CLASS_KEYS, |
| new String[] { referencedClassMapping.getJaxbType().getFullyQualifiedName(), this.referencedXmlPath }, |
| ELJavaXmlJoinNode.this, |
| getReferencedXmlPathTextRange(astRoot))); |
| } |
| |
| XsdTypeDefinition xsdType = getAttributeMapping().getReferencedXsdTypeDefinition(); |
| XPath xpath = XPathFactory.instance().getXpath(this.referencedXmlPath); |
| xpath.validate(new ReferencedXmlPathContext(astRoot), xsdType, messages); |
| } |
| |
| protected TextRange getXmlPathTextRange(CompilationUnit astRoot) { |
| // should never be null |
| return getAnnotation().getXmlPathTextRange(astRoot); |
| } |
| |
| protected TextRange getReferencedXmlPathTextRange(CompilationUnit astRoot) { |
| // should never be null |
| return getAnnotation().getReferencedXmlPathTextRange(astRoot); |
| } |
| |
| |
| public interface Context { |
| |
| XmlJoinNodeAnnotation getAnnotation(); |
| |
| ELXmlJoinNodesMapping getAttributeMapping(); |
| } |
| |
| |
| protected abstract class XPathContext |
| implements XPath.Context { |
| |
| protected CompilationUnit astRoot; |
| |
| protected XPathContext(CompilationUnit astRoot) { |
| this.astRoot = astRoot; |
| } |
| |
| |
| public JaxbNode getContextObject() { |
| return ELJavaXmlJoinNode.this; |
| } |
| |
| public JaxbPackage getJaxbPackage() { |
| return ELJavaXmlJoinNode.this.getJaxbPackage(); |
| } |
| } |
| |
| |
| protected class XmlPathContext |
| extends XPathContext { |
| |
| protected XmlPathContext(CompilationUnit astRoot) { |
| super(astRoot); |
| } |
| |
| |
| public TextRange getTextRange() { |
| return ELJavaXmlJoinNode.this.getXmlPathTextRange(this.astRoot); |
| } |
| } |
| |
| |
| protected class ReferencedXmlPathContext |
| extends XPathContext { |
| |
| protected ReferencedXmlPathContext(CompilationUnit astRoot) { |
| super(astRoot); |
| } |
| |
| |
| public TextRange getTextRange() { |
| return ELJavaXmlJoinNode.this.getReferencedXmlPathTextRange(this.astRoot); |
| } |
| } |
| } |