// ============================================================================ // // Copyright (C) 2006-2016 Talend Inc. - www.talend.com // // This source code is available under agreement available at // %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt // // You should have received a copy of the agreement // along with this program; if not, write to Talend SA // 9 rue Pages 92150 Suresnes, France // // ============================================================================ package com.amalto.workbench.providers; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.emf.common.util.EList; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.xsd.XSDAnnotation; import org.eclipse.xsd.XSDAttributeGroupDefinition; import org.eclipse.xsd.XSDComplexTypeDefinition; import org.eclipse.xsd.XSDElementDeclaration; import org.eclipse.xsd.XSDIdentityConstraintDefinition; import org.eclipse.xsd.XSDModelGroup; import org.eclipse.xsd.XSDParticle; import org.eclipse.xsd.XSDSchema; import org.eclipse.xsd.XSDSimpleTypeDefinition; import org.eclipse.xsd.XSDTerm; import org.eclipse.xsd.XSDTypeDefinition; import org.eclipse.xsd.XSDVariety; import org.eclipse.xsd.XSDWildcard; import org.eclipse.xsd.util.XSDConstants; import org.w3c.dom.Document; import org.w3c.dom.Element; import com.amalto.workbench.models.TreeObject; import com.amalto.workbench.utils.DataModelFilter; import com.amalto.workbench.utils.Util; import com.amalto.workbench.utils.XSDAnnotationsStructure; public class XSDTreeContentProvider implements IStructuredContentProvider, ITreeContentProvider, ISchemaContentProvider { private static Log log = LogFactory.getLog(XSDTreeContentProvider.class); protected XSDSchema xsdSchema; IWorkbenchPartSite site = null; DataModelFilter filter; TreeObject treeObj; public XSDTreeContentProvider(IWorkbenchPartSite site, XSDSchema invisibleRoot, TreeObject treeObject) { this.site = site; this.xsdSchema = invisibleRoot; } public void inputChanged(Viewer v, Object oldInput, Object newInput) { } public void dispose() { } public Object[] getElements(Object parent) { if (parent.equals(site)) { return getChildren(xsdSchema); } return getChildren(parent); } public Object getParent(Object child) { // System.out.println("get Parent "+child.getClass().getName()); return null; } public void setFilter(DataModelFilter filter) { this.filter = filter; } public Object[] getChildren(Object parent) { // if (parent == null) { // log.info("NULL PARENT"); // } // log.info("get Children "+parent.getClass().getName()+ " -- "+parent.toString()); if (parent instanceof XSDSchema) { EList xsdElementDeclarations = xsdSchema.getElementDeclarations(); List<XSDElementDeclaration> list = new ArrayList<XSDElementDeclaration>(); if (filter != null && !filter.isAll()) { for (XSDElementDeclaration el : (XSDElementDeclaration[]) xsdElementDeclarations .toArray(new XSDElementDeclaration[xsdElementDeclarations.size()])) { if (isInclude(el.getAnnotation())) { list.add(el); } } return filterOutDuplicatedElems(list); } return filterOutDuplicatedElems(xsdElementDeclarations); } if (parent instanceof XSDAttributeGroupDefinition) { XSDAttributeGroupDefinition attributeGroupDefinition = (XSDAttributeGroupDefinition) parent; if (attributeGroupDefinition.getContents().size() == 0) // a ref attributeGroupDefinition = attributeGroupDefinition.getResolvedAttributeGroupDefinition(); return attributeGroupDefinition.getContents().toArray(new Object[attributeGroupDefinition.getContents().size()]); } if (parent instanceof XSDParticle) { // a particle inside a choice or sequence or whatever XSDParticle xsdParticle = (XSDParticle) parent; return getXSDParticleChildren(xsdParticle); }// XSDParticle /* * if (parent instanceof XSDTypeDefinition) { * * if (parent instanceof XSDSimpleTypeDefinition) { XSDSimpleTypeDefinition std = (XSDSimpleTypeDefinition) * parent; if (std.getVariety().equals(XSDVariety.ATOMIC_LITERAL)) { ArrayList list = new ArrayList(); //add * Base Type if not a pre-defined type if (! * std.getSchema().getSchemaForSchema().getTypeDefinitions().contains(std)) * list.add(std.getBaseTypeDefinition()); list.addAll(std.getFacetContents()); return list.toArray(new * Object[list.size()]); } if (std.getVariety().equals(XSDVariety.LIST_LITERAL)) { //FIXME: How do we indicate * it is a LIST? return new XSDSimpleTypeDefinition[] {std.getBaseTypeDefinition()}; } if * (std.getVariety().equals(XSDVariety.UNION_LITERAL)) return (XSDSimpleTypeDefinition[]) * (std.getMemberTypeDefinitions().toArray(new XSDSimpleTypeDefinition[std.getMemberTypeDefinitions().size()])); * //return new Object[]{std.getBaseTypeDefinition()}; } if (parent instanceof XSDComplexTypeDefinition) { * XSDComplexTypeContent xsdComplexTypeContent = ((XSDComplexTypeDefinition) parent).getContent(); * * ArrayList<Object> list = new ArrayList<Object>(); * list.addAll(((XSDComplexTypeDefinition)parent).getAttributeContents()); * * if (xsdComplexTypeContent == null) { XSDComplexTypeDefinition ctd = (XSDComplexTypeDefinition) parent; * list.add(ctd.getBaseTypeDefinition()); return list.toArray(new Object[list.size()]); } else { if * (xsdComplexTypeContent instanceof XSDSimpleTypeDefinition) { list.add(xsdComplexTypeContent); return * list.toArray(new Object[list.size()]); } if (xsdComplexTypeContent instanceof XSDParticle) return * getXSDParticleChildren((XSDParticle)xsdComplexTypeContent); //return children * list.add(((XSDComplexTypeDefinition) parent).getContent()); return list.toArray(new Object[list.size()]); } } * * } */ /* * if (parent instanceof XSDElementDeclaration) { ArrayList<Object> list = new ArrayList<Object>(); * * //handle extensions and retrictions directly XSDTypeDefinition typeDefinition = * ((XSDElementDeclaration)parent).getTypeDefinition(); if (typeDefinition instanceof XSDComplexTypeDefinition) * { XSDComplexTypeDefinition complexTypeDefinition = (XSDComplexTypeDefinition) typeDefinition; if * (complexTypeDefinition.getContent() == null) list.add(complexTypeDefinition.getBaseTypeDefinition()); else * list.add(complexTypeDefinition); } else { list.add(((XSDElementDeclaration)parent).getTypeDefinition()); } * * list.addAll(((XSDElementDeclaration)parent).getIdentityConstraintDefinitions()); return list.toArray(new * Object[list.size()]); } */ if (parent instanceof XSDModelGroup) { XSDModelGroup modelGroup = ((XSDModelGroup) parent); EList list = modelGroup.getContents(); List<XSDParticle> ls = new ArrayList<XSDParticle>(); if (filter != null && !filter.isAll()) { for (XSDParticle el : (XSDParticle[]) list.toArray(new XSDParticle[list.size()])) { XSDTerm tm = el.getTerm(); if (tm instanceof XSDElementDeclaration) { XSDAnnotation annotation = ((XSDElementDeclaration) tm).getAnnotation(); if (isInclude(annotation)) { ls.add(el); } } } return ls.toArray(new XSDParticle[ls.size()]); } return list.toArray(new Object[list.size()]); } if (parent instanceof XSDSimpleTypeDefinition) { XSDSimpleTypeDefinition std = (XSDSimpleTypeDefinition) parent; if (std.getVariety().equals(XSDVariety.ATOMIC_LITERAL)) { ArrayList list = new ArrayList(); // add Base Type if not a pre-defined type if (std != null && std.getSchema() != null && std.getSchema().getSchemaForSchema() != null) if (!std.getSchema().getSchemaForSchema().getTypeDefinitions().contains(std)) list.add(std.getBaseTypeDefinition()); list.addAll(std.getFacetContents()); return list.toArray(new Object[list.size()]); } if (std.getVariety().equals(XSDVariety.LIST_LITERAL)) { // FIXME: How do we indicate it is a LIST? return new XSDSimpleTypeDefinition[] { std.getBaseTypeDefinition() }; } if (std.getVariety().equals(XSDVariety.UNION_LITERAL)) return std.getMemberTypeDefinitions().toArray(new XSDSimpleTypeDefinition[std.getMemberTypeDefinitions().size()]); // return new Object[]{std.getBaseTypeDefinition()}; } if (parent instanceof XSDElementDeclaration) { // abstract elements do not have children if (((XSDElementDeclaration) parent).isAbstract()) return new Object[0]; ArrayList<Object> list = new ArrayList<Object>(); // handle extensions and restrictions directly XSDTypeDefinition typeDefinition = ((XSDElementDeclaration) parent).getTypeDefinition(); if (typeDefinition instanceof XSDComplexTypeDefinition) { list.addAll(Util.getComplexTypeDefinitionChildren((XSDComplexTypeDefinition) typeDefinition)); } else { list.add(((XSDElementDeclaration) parent).getTypeDefinition()); } // the keys if (filter != null && !filter.isAll()) { } else { list.addAll(((XSDElementDeclaration) parent).getIdentityConstraintDefinitions()); } // the annotations XSDAnnotation annotation = ((XSDElementDeclaration) parent).getAnnotation(); if (filter != null && !filter.isAll()) { } else { if (annotation != null) { list.add(annotation); } } return list.toArray(new Object[list.size()]); } if (parent instanceof XSDIdentityConstraintDefinition) { ArrayList list = new ArrayList(); if (filter != null && !filter.isAll()) { } else { list.add(((XSDIdentityConstraintDefinition) parent).getSelector()); list.addAll(((XSDIdentityConstraintDefinition) parent).getFields()); } return list.toArray(new Object[list.size()]); } if (parent instanceof XSDAnnotation) { ArrayList list = new ArrayList(); if (filter != null && !filter.isAll()) { } else { XSDAnnotation annotation = (XSDAnnotation) parent; list.addAll(annotation.getUserInformation()); list.addAll(annotation.getApplicationInformation()); } return list.size() == 0 ? new Object[0] : list.toArray(new Object[list.size()]); } if (parent instanceof Element) { // appinfos return new Object[0]; } // log.info("getChildren: UNPROCESSED PARENT: "+parent.getClass().getName()+": "+parent); return new Object[0]; } private boolean isInclude(XSDAnnotation annotation) { boolean include = false; if (annotation != null) { XSDAnnotationsStructure annotion = new XSDAnnotationsStructure(annotation); if ((annotion.getWriteAccesses().values().contains(filter.getRole()) && filter.isWriteAccess())) { return true; } if ((annotion.getHiddenAccesses().values().contains(filter.getRole()) && filter.isHiddenAccess())) { return true; } } else { if ((filter.isReadOnly())) { return true; } } return include; } private Object[] getXSDParticleChildren(XSDParticle particle) { // System.out.println("getXSDParticleChildren() CLASS "+particle.getClass().getName()); // System.out.println("getXSDParticleChildren() TERM "+particle.getTerm().getClass().getName()+": "+particle.getTerm()); XSDTerm term = particle.getTerm(); if (term instanceof XSDElementDeclaration) { XSDTypeDefinition typeDef = ((XSDElementDeclaration) term).getTypeDefinition(); if (typeDef == null) return new Object[0]; // elements with not type declaration (allowed) ArrayList<Object> list = new ArrayList<Object>(); if (typeDef instanceof XSDComplexTypeDefinition) { list.addAll(Util.getComplexTypeDefinitionChildren((XSDComplexTypeDefinition) typeDef)); } else { list.add(typeDef); } list.addAll(((XSDElementDeclaration) term).getIdentityConstraintDefinitions()); XSDAnnotation annotation = ((XSDElementDeclaration) term).getAnnotation(); if (filter != null && !filter.isAll()) { } else { if (annotation != null) { list.add(annotation); } } return list.toArray(new Object[list.size()]); } if (term instanceof XSDModelGroup) {// a ModelGroup skip it and get children directtly EList list = ((XSDModelGroup) term).getContents(); return list.toArray(new XSDParticle[list.size()]); } if (term instanceof XSDWildcard) { } return new Object[] {}; } private Object[] filterOutDuplicatedElems(List<XSDElementDeclaration> xsdElementDeclarations) { List<XSDElementDeclaration> list = new ArrayList<XSDElementDeclaration>(); for (XSDElementDeclaration el : (XSDElementDeclaration[]) xsdElementDeclarations .toArray(new XSDElementDeclaration[xsdElementDeclarations.size()])) { boolean exist = false; for (XSDElementDeclaration xsdEl : list) { if (xsdEl.getName().equals(el.getName()) && xsdEl.getTargetNamespace() != null && el.getTargetNamespace() != null && xsdEl.getTargetNamespace().equals(el.getTargetNamespace())) { exist = true; break; } else if (xsdEl.getName().equals(el.getName()) && xsdEl.getTargetNamespace() == null && el.getTargetNamespace() == null) { exist = true; break; } } if (!exist && (el.getTargetNamespace() != null && !el.getTargetNamespace().equals( XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001)) || el.getTargetNamespace() == null) { list.add(el); } } return list.toArray(new Object[] {}); } public boolean hasChildren(Object parent) { // System.out.println("has Children "+parent.getClass().getName()); return getChildren(parent).length > 0; } public XSDSchema getXsdSchema() { return xsdSchema; } public void setXsdSchema(String xsd) { try { xsdSchema = Util.createXsdSchema(xsd, treeObj); } catch (Exception e) { log.error(e.getMessage(), e); } } public void setXsdSchema(XSDSchema xsdSchema) { this.xsdSchema = xsdSchema; } public String getXSDSchemaAsString() throws Exception { Document document = xsdSchema.getDocument(); String schema = Util.nodeToString(document); // FIXES a bug in the XSD library that puts nillable attributes in elements which are ref // That is illegal according to W3C ยง3.3.3 / 2.2 (and Xerces) Pattern p = Pattern.compile("(<([a-z]+:)?element.*?)nillable=['|\"].*?['|\"](.*?ref=.*?>)");//$NON-NLS-1$ schema = p.matcher(schema).replaceAll("$1 $3");//$NON-NLS-1$ return schema; } /* * public void addListener(IXObjectModelListener listener) { xsdSchema. } public void * removeListener(IXObjectModelListener listener) { invisibleRoot.removeListener(listener); } */ }