/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.metamodels.xml.util; import java.util.Iterator; import java.util.List; import org.eclipse.emf.ecore.EObject; import org.eclipse.xsd.XSDComplexTypeDefinition; import org.eclipse.xsd.XSDComponent; import org.eclipse.xsd.XSDDerivationMethod; import org.eclipse.xsd.XSDElementDeclaration; import org.eclipse.xsd.XSDFeature; import org.eclipse.xsd.XSDTypeDefinition; import org.eclipse.xsd.util.XSDConstants; import org.teiid.core.designer.util.CoreStringUtil; import org.teiid.designer.metamodels.xml.BuildStatus; import org.teiid.designer.metamodels.xml.ProcessingInstruction; import org.teiid.designer.metamodels.xml.XmlAll; import org.teiid.designer.metamodels.xml.XmlAttribute; import org.teiid.designer.metamodels.xml.XmlBuildable; import org.teiid.designer.metamodels.xml.XmlChoice; import org.teiid.designer.metamodels.xml.XmlComment; import org.teiid.designer.metamodels.xml.XmlContainerNode; import org.teiid.designer.metamodels.xml.XmlDocumentEntity; import org.teiid.designer.metamodels.xml.XmlDocumentNode; import org.teiid.designer.metamodels.xml.XmlDocumentPlugin; import org.teiid.designer.metamodels.xml.XmlElement; import org.teiid.designer.metamodels.xml.XmlFragment; import org.teiid.designer.metamodels.xml.XmlNamespace; import org.teiid.designer.metamodels.xml.XmlSequence; /** * XmlDocumentUtil * * @since 8.0 */ public class XmlDocumentUtil { public static final int XSD_OCCURRENCE_NONE = 0; public static final int XSD_OCCURRENCE_N = 1; public static final int XSD_OCCURRENCE_NToM = 2; public static final int XSD_OCCURRENCE_NToUnbounded = 3; public static final int XSD_OCCURRENCE_One = 4; public static final int XSD_OCCURRENCE_OneToN = 5; public static final int XSD_OCCURRENCE_OneToUnbounded = 6; public static final int XSD_OCCURRENCE_Zero = 7; public static final int XSD_OCCURRENCE_ZeroToN = 8; public static final int XSD_OCCURRENCE_ZeroToOne = 9; public static final int XSD_OCCURRENCE_ZeroToUnbounded = 10; /** Moved from XmlDocumentBuilderImpl: */ private static final String ANY_TYPE = "anyType"; //$NON-NLS-1$ /** * Hidden constructor to prevent instantiation. */ private XmlDocumentUtil() { super(); } public static String createXmlPrefixFromUri(final String uri){ if(uri == null){ return ""; //$NON-NLS-1$ } if (uri.equals(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001) || uri.equals(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2000_10) || uri.equals(XSDConstants.SCHEMA_FOR_SCHEMA_URI_1999)) { return "xs"; //$NON-NLS-1$ } if (uri.equals(XSDConstants.SCHEMA_INSTANCE_URI_2001)) { return "xsi"; //$NON-NLS-1$ } int index = uri.lastIndexOf("/"); //$NON-NLS-1$ // No Fwd slash found if(index == -1) { // Look for Dbl backslash index = uri.lastIndexOf("\\"); //$NON-NLS-1$ } // if Neither found, reset index to 0 (otherwise increment past it) if (index==-1) { index = 0; } else { index++; } // keep name past slashes. If any colons, replace with underscores final String name = uri.substring(index).replace(':', '_'); //remove file extension final int i2 = name.lastIndexOf("."); //$NON-NLS-1$ if(i2 == -1){ return name; } return name.substring(0, i2); } public static String getPathInDocument( XmlDocumentEntity entity ) { String path = null; while ( entity != null ) { String segment = null; if ( entity instanceof XmlFragment ) { break; // stop when we see the document/fragment } if ( entity instanceof XmlNamespace ) { final XmlNamespace namespace = (XmlNamespace)entity; segment = "@xmlns:" + namespace.getPrefix(); //$NON-NLS-1$ } else if ( entity instanceof XmlElement ) { final XmlElement element = (XmlElement)entity; segment = element.getName(); } else if ( entity instanceof XmlAttribute ) { final XmlAttribute attribute = (XmlAttribute)entity; segment = "@" + attribute.getName(); //$NON-NLS-1$ } else if ( entity instanceof XmlContainerNode ) { if ( entity instanceof XmlSequence ) { segment = XmlDocumentPlugin.Util.getString("_UI_XmlSequence_type"); //$NON-NLS-1$ } else if ( entity instanceof XmlChoice ) { segment = XmlDocumentPlugin.Util.getString("_UI_XmlChoice_type"); //$NON-NLS-1$ } else if ( entity instanceof XmlAll ) { segment = XmlDocumentPlugin.Util.getString("_UI_XmlAll_type"); //$NON-NLS-1$ } } else if ( entity instanceof XmlComment ) { final XmlComment comment = (XmlComment)entity; String text = comment.getText(); segment = "<!-- "; //$NON-NLS-1$ if ( text != null ) { segment = segment + text; } segment = segment + " -->"; //$NON-NLS-1$ if ( segment.length() > 21 ) { segment = segment.substring(0,20) + "... -->"; //$NON-NLS-1$ } } else if ( entity instanceof ProcessingInstruction ) { final ProcessingInstruction instructions = (ProcessingInstruction)entity; String target = instructions.getTarget(); String rawText = instructions.getRawText(); segment = "<?"; //$NON-NLS-1$ if ( target != null && target.trim().length() != 0 ) { segment = segment + target; } if ( rawText != null && rawText.trim().length() != 0 ) { segment = segment + " " + rawText; //$NON-NLS-1$ } segment = segment + " ?>"; //$NON-NLS-1$ if ( segment.length() > 21 ) { segment = segment.substring(0,20) + "... ?>"; //$NON-NLS-1$ } } if ( segment == null ) { segment = CoreStringUtil.Constants.EMPTY_STRING; } if ( path == null ) { path = segment; } else { path = segment + "/" + path; //$NON-NLS-1$ } entity = (XmlDocumentEntity) entity.eContainer(); } if ( path == null ) { return "/"; //$NON-NLS-1$ } return "/" + path; //$NON-NLS-1$ } public static String getXPath( XmlDocumentEntity entity ) { String path = null; while ( entity != null ) { String segment = null; if ( entity instanceof XmlFragment ) { break; // stop when we see the document/fragment } if ( entity instanceof XmlNamespace ) { final XmlNamespace namespace = (XmlNamespace)entity; segment = "@xmlns:" + namespace.getPrefix(); //$NON-NLS-1$ } else if ( entity instanceof XmlElement ) { final XmlElement element = (XmlElement)entity; segment = element.getName(); } else if ( entity instanceof XmlAttribute ) { final XmlAttribute attribute = (XmlAttribute)entity; segment = "@" + attribute.getName(); //$NON-NLS-1$ } else if ( entity instanceof XmlContainerNode ) { entity = (XmlDocumentEntity) entity.eContainer(); continue; // skip container nodes } else if ( entity instanceof XmlComment ) { entity = (XmlDocumentEntity) entity.eContainer(); continue; // skip container nodes } else if ( entity instanceof ProcessingInstruction ) { entity = (XmlDocumentEntity) entity.eContainer(); continue; // skip container nodes } if ( segment == null ) { segment = CoreStringUtil.Constants.EMPTY_STRING; } if ( path == null ) { path = segment; } else { path = segment + "/" + path; //$NON-NLS-1$ } entity = (XmlDocumentEntity) entity.eContainer(); } if ( path == null ) { return "/"; //$NON-NLS-1$ } return "/" + path; //$NON-NLS-1$ } /** Is the specified document node a complex type? * @param dnode the node to analyze * @return whether dnode has a complex type */ public static boolean hasComplexType(Object object) { if (object instanceof XmlDocumentNode) { XmlDocumentNode dnode = (XmlDocumentNode) object; XSDComponent xcomp = dnode.getXsdComponent(); XSDTypeDefinition xtype = findXSDType(xcomp); return xtype instanceof XSDComplexTypeDefinition; } return false; } /** Moved from XmlDocumentBuilderImpl: */ public static boolean isAnyType(final EObject obj){ if(obj instanceof XSDTypeDefinition){ if (ANY_TYPE.equals(((XSDTypeDefinition)obj).getName()) ){ return true; } } return false; } /** * Return the type definition for the given XmlDocumentNode * @param docNode the type definition for the given XmlDocumentNode - may not be null * @return the XSDTypeDefinition of the node, if it is an XmlDocumentNode, or null * otherwise. */ public static XSDTypeDefinition findXSDType(Object node) { if (node instanceof XmlDocumentNode) { XmlDocumentNode docNode = (XmlDocumentNode) node; return findXSDType(docNode.getXsdComponent()); } //endif return null; } /** Moved from XmlDocumentBuilderImpl: * Return the type definition for the given schemaComponent - may be null * @param the type definition for the given schemaComponent - may be null */ public static XSDTypeDefinition findXSDType(final XSDComponent schemaComponent) { if(schemaComponent instanceof XSDElementDeclaration){ Object ref = ((XSDElementDeclaration)schemaComponent).getResolvedElementDeclaration(); return (ref == null) ? null : ((XSDElementDeclaration)ref).getType(); }else if(schemaComponent instanceof XSDTypeDefinition){ if(schemaComponent instanceof XSDComplexTypeDefinition) { final XSDDerivationMethod der = ((XSDComplexTypeDefinition)schemaComponent).getDerivationMethod(); if(der != null && der.getValue() == XSDDerivationMethod.RESTRICTION) { return null; } } final XSDTypeDefinition baseType = ((XSDTypeDefinition)schemaComponent).getBaseType(); if(baseType == null || baseType == schemaComponent || isAnyType(baseType) ){ return null; } return baseType; }else if(schemaComponent instanceof XSDFeature){ return ((XSDFeature)schemaComponent).getType(); } return null; } /** Examine whether the Exclude from Document property is set. * @param element the element to analyze * @param checkHierarchy if true, examine parents for isExcluded until * an excluded parent is found (returns true) or XMLRoot is * encountered (returns false) * @return the value of the ExcludeFromDocument property if * element is an XmlElement or XmlContainerNode, false otherwise */ public static boolean isExcluded(Object element, boolean checkHierarchy) { // enclose with a generic instanceof to weed things out early // if they aren't even in the XML hierarchy. if (element instanceof XmlDocumentEntity) { if (element instanceof XmlElement) { XmlElement e = (XmlElement) element; return e.isExcludeFromDocument() || (checkHierarchy && isExcluded(e.getParent(), checkHierarchy)); } else if (element instanceof XmlContainerNode) { XmlContainerNode e = (XmlContainerNode) element; return e.isExcludeFromDocument() || (checkHierarchy && isExcluded(e.getParent(), checkHierarchy)); // Look for other things, like attributes, namespace declarations, etc: } else if (element instanceof XmlAttribute) { XmlAttribute e = (XmlAttribute)element; return e.isExcludeFromDocument() || (checkHierarchy && isExcluded(e.getElement(), checkHierarchy)); } else if (element instanceof XmlComment) { XmlComment e = (XmlComment)element; return checkHierarchy && isExcluded(e.getParent(), checkHierarchy); } else if (element instanceof XmlNamespace) { XmlNamespace e = (XmlNamespace)element; return checkHierarchy && isExcluded(e.getElement(), checkHierarchy); } else if (element instanceof ProcessingInstruction) { ProcessingInstruction e = (ProcessingInstruction)element; return checkHierarchy && isExcluded(e.getParent(), checkHierarchy); } //endif } // endif return false; } /** Sets the ExcludeFromDocument property on XmlElements and XmlContainerNodes. * @param element the element to change * @param exclude the value to set */ public static void setExcluded(Object element, boolean exclude) { if (element instanceof XmlDocumentNode) { XmlDocumentNode xe = (XmlDocumentNode) element; xe.setExcludeFromDocument(exclude); } else if (element instanceof XmlContainerNode) { XmlContainerNode xcn = (XmlContainerNode) element; xcn.setExcludeFromDocument(exclude); } } /** Examine whether the Recursive property is set. * @param element the element to analyze * @return the value of the Recursive property if * element is an XmlElement, false otherwise */ public static boolean isRecursive(Object element) { if (element instanceof XmlElement) { XmlElement xe = (XmlElement) element; return xe.isRecursive(); } // endif return false; } /** Sets the Recursive property on XmlElements. * @param element the element to change * @param recurse the value to set */ public static void setRecursive(Object element, boolean recurse) { if (element instanceof XmlElement) { XmlElement xe = (XmlElement) element; xe.setRecursive(recurse); } // endif } /** Examine whether the BuildStatus property is set to INCOMPLETE. * @param element the element to analyze * @return true if element is an XmlBuildable and the value of the * BuildStatus property is INCOMPLETE, false otherwise */ public static boolean isIncomplete(Object element) { if (element instanceof XmlBuildable) { XmlBuildable xb = (XmlBuildable) element; return xb.getBuildState() == BuildStatus.INCOMPLETE_LITERAL; } // endif return false; } /** Sets the BuildStatus property on XmlBuildables. * @param element the element to change * @param stopped the value to set. If true, the BuildStatus * property will be set to INCOMPLETE. If false, COMPLETE. */ public static void setIncomplete(Object element, boolean stopped) { if (element instanceof XmlBuildable) { XmlBuildable xb = (XmlBuildable) element; BuildStatus bs = (stopped)?BuildStatus.INCOMPLETE_LITERAL:BuildStatus.COMPLETE_LITERAL; xb.setBuildState(bs); } // endif } public static boolean hasElementChildren(XmlDocumentEntity node) { Iterator itor = node.eContents().iterator(); while (itor.hasNext()) { XmlDocumentEntity kid = (XmlDocumentEntity) itor.next(); if (kid instanceof XmlElement) { return true; } // endif } // endwhile return false; } public static int getCardinality(Object element) { if (element instanceof XmlDocumentNode) { int min = ((XmlDocumentNode) element).getMinOccurs(); int max = ((XmlDocumentNode) element).getMaxOccurs(); if (min == 0) { if (min == max) { return XSD_OCCURRENCE_Zero; } else if (max == 1) { return XSD_OCCURRENCE_ZeroToOne; } else if (max == -1) { return XSD_OCCURRENCE_ZeroToUnbounded; } else if (max > min) { return XSD_OCCURRENCE_ZeroToN; } } else if (min == 1) { if (min == max) { return XSD_OCCURRENCE_One; } else if (max == -1) { return XSD_OCCURRENCE_OneToUnbounded; } else if (max > min) { return XSD_OCCURRENCE_OneToN; } } else if (min > 1) { if (min == max) { return XSD_OCCURRENCE_N; } else if (max == -1) { return XSD_OCCURRENCE_NToUnbounded; } else if (max > min) { return XSD_OCCURRENCE_NToM; } } } return XSD_OCCURRENCE_NONE; } public static void setAllExcluded(XmlDocumentEntity element, boolean excluded) { List l = element.eContents(); Iterator itor = l.iterator(); while (itor.hasNext()) { XmlDocumentEntity node = (XmlDocumentEntity) itor.next(); setAllExcluded(node, excluded); } // endwhile // set my own excluded property: setExcluded(element, excluded); } }