// ============================================================================
//
// 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.XSDComplexTypeContent;
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 TypesContentProvider implements IStructuredContentProvider, ITreeContentProvider, ISchemaContentProvider {
private static Log log = LogFactory.getLog(TypesContentProvider.class);
protected XSDSchema xsdSchema;
IWorkbenchPartSite site = null;
DataModelFilter filter;
TreeObject treeObj;
public TypesContentProvider(IWorkbenchPartSite site, XSDSchema invisibleRoot, TreeObject treeObject) {
this.site = site;
this.xsdSchema = invisibleRoot;
this.treeObj = treeObject;
}
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.getTypeDefinitions();
List<XSDTypeDefinition> list = new ArrayList<XSDTypeDefinition>();
for (XSDTypeDefinition el : (XSDTypeDefinition[]) xsdElementDeclarations
.toArray(new XSDTypeDefinition[xsdElementDeclarations.size()])) {
// if( el instanceof XSDComplexTypeDefinition){
boolean exist = false;
for (XSDTypeDefinition type : list) {
if (type.getName().equals(el.getName()) && type.getTargetNamespace() != null
&& el.getTargetNamespace() != null && type.getTargetNamespace().equals(el.getTargetNamespace())) {
exist = true;
break;
} else if (type.getName().equals(el.getName()) && type.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);
}
// }
}
// for (XSDSchemaContent xsdComp : xsdSchema.getContents()) {
// if (xsdComp instanceof XSDImport) {
// list.addAll(Util.getImportedTypeDefinitionChildren((XSDImport)xsdComp));
// }
// }
return list.toArray(new XSDTypeDefinition[list.size()]);
// return xsdElementDeclarations.toArray(new XSDTypeDefinition[xsdElementDeclarations.size()] );
}
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 != 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 (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.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 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];
}
// System.out.println("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(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 ArrayList<Object> getComplexTypeDefinitionChildren(XSDComplexTypeDefinition complexTypeDefinition) {
// System.out.println("getComplexTypeDefinitionChildren "+complexTypeDefinition+": "+complexTypeDefinition.getContent());
// System.out.println(
// "getComplexTypeDefinitionChildren BASE TYPE "+
// complexTypeDefinition.getBaseTypeDefinition().getName()+" : "+
// complexTypeDefinition.getDerivationMethod().getName()
// );
XSDComplexTypeContent xsdComplexTypeContent = complexTypeDefinition.getContent();
ArrayList<Object> list = new ArrayList<Object>();
// Now determine whether ref. If ref look at the base Type definition
if (xsdComplexTypeContent == null) {
XSDTypeDefinition typeDefinition = complexTypeDefinition.getBaseTypeDefinition();
// if a simple type return the simple type
if (typeDefinition instanceof XSDSimpleTypeDefinition) {
list.add(typeDefinition);
return list;
} else {
}
// it is a complex Type
xsdComplexTypeContent = ((XSDComplexTypeDefinition) typeDefinition).getContent();
}
// check if we are extending a complex Definition
if ("extension".equals(complexTypeDefinition.getDerivationMethod().getName())) {//$NON-NLS-1$
if (complexTypeDefinition.getBaseTypeDefinition() instanceof XSDComplexTypeDefinition) {
list.addAll(getComplexTypeDefinitionChildren((XSDComplexTypeDefinition) complexTypeDefinition
.getBaseTypeDefinition()));
}
}
// Attributes
if (complexTypeDefinition.getAttributeContents() != null)
list.addAll(complexTypeDefinition.getAttributeContents());
// Annotations
if (complexTypeDefinition.getAnnotations() != null)
list.addAll(complexTypeDefinition.getAnnotations());
// now check what we have in the content
// simple type return the simple type
if (xsdComplexTypeContent instanceof XSDSimpleTypeDefinition) {
list.add(xsdComplexTypeContent);
return list;
}
// xsd Particle: we have a model group
if (xsdComplexTypeContent instanceof XSDParticle) {
// System.out.println("Model Group?: "+((XSDParticle)xsdComplexTypeContent).getTerm());
if (((XSDParticle) xsdComplexTypeContent).getTerm() instanceof XSDModelGroup) {
// return the model group
list.add(((XSDParticle) xsdComplexTypeContent).getTerm());
return list;
} else { // wild card or element declaration '?)
list.add(((XSDParticle) xsdComplexTypeContent).getTerm());
return list;
}
}
// what else could it be ?
list.add(xsdComplexTypeContent);
return list;
}
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); }
*/
}