// ============================================================================ // // 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.actions; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.xsd.XSDAnnotation; import org.eclipse.xsd.XSDComplexTypeDefinition; import org.eclipse.xsd.XSDCompositor; import org.eclipse.xsd.XSDDerivationMethod; import org.eclipse.xsd.XSDElementDeclaration; import org.eclipse.xsd.XSDFactory; import org.eclipse.xsd.XSDModelGroup; import org.eclipse.xsd.XSDParticle; import org.eclipse.xsd.XSDSimpleTypeDefinition; import org.eclipse.xsd.XSDTerm; import org.eclipse.xsd.XSDTypeDefinition; import org.eclipse.xsd.util.XSDSchemaBuildingTools; import org.w3c.dom.Element; import com.amalto.workbench.dialogs.ComplexTypeInputDialogR; import com.amalto.workbench.editors.DataModelMainPage; import com.amalto.workbench.i18n.Messages; import com.amalto.workbench.utils.Util; import com.amalto.workbench.utils.XSDAnnotationsStructure; public class XSDAddComplexTypeElementAction extends UndoAction { private static Log log = LogFactory.getLog(XSDAddComplexTypeElementAction.class); private final String defaultTypeName = "string"; //$NON-NLS-1$ private XSDParticle selParticle = null; private XSDModelGroup modelGroup = null; private ComplexTypeInputDialogR dialogR; private String elementName; private int minOccurs; private int maxOccurs; private String superTypeName; private String typeName; private boolean isAbstract; private boolean isChoice; private boolean isAll; public XSDAddComplexTypeElementAction(DataModelMainPage page) { super(page); setText(Messages._AddCType); } @Override public IStatus doAction() { if (!init()) { return Status.CANCEL_STATUS; } if (openDialog() == Dialog.CANCEL) { return Status.CANCEL_STATUS; } updateElementFields(); if (!changeElementTypeToSequence()) { return Status.CANCEL_STATUS; } if (!createComplexTypeParticle()) { return Status.CANCEL_STATUS; } return Status.OK_STATUS; } private boolean init() { IStructuredSelection selection = (IStructuredSelection) page.getTreeViewer().getSelection(); if (selection.getFirstElement() instanceof XSDParticle) { selParticle = (XSDParticle) selection.getFirstElement(); if (!(selParticle.getContainer() instanceof XSDModelGroup)) { return false; } modelGroup = (XSDModelGroup) selParticle.getContainer(); } else { if (selection.getFirstElement() instanceof XSDComplexTypeDefinition) { XSDComplexTypeDefinition ctd = (XSDComplexTypeDefinition) selection.getFirstElement(); if (!(ctd.getContent() instanceof XSDParticle)) { return false; } if (!(((XSDParticle) ctd.getContent()).getTerm() instanceof XSDModelGroup)) { return false; } ; modelGroup = (XSDModelGroup) ((XSDParticle) ctd.getContent()).getTerm(); } else if (selection.getFirstElement() instanceof XSDParticle) { modelGroup = (XSDModelGroup) ((XSDParticle) selection.getFirstElement()).getTerm(); } else if (selection.getFirstElement() instanceof XSDModelGroup) { modelGroup = (XSDModelGroup) selection.getFirstElement(); } else { log.info(Messages.bind(Messages._UnkownSection, selection.getFirstElement().getClass().getName(), selection .getFirstElement().toString())); return false; } } return true; } private int openDialog() { XSDSimpleTypeDefinition simpleTypeDefinition = schema.resolveSimpleTypeDefinition(schema.getSchemaForSchemaNamespace(), defaultTypeName); List<XSDComplexTypeDefinition> types = Util.getComplexTypes(schema); dialogR = new ComplexTypeInputDialogR(page.getSite().getShell(), Messages._AddCType, modelGroup, schema, types, simpleTypeDefinition, false, false); dialogR.setBlockOnOpen(true); int ret = dialogR.open(); return ret; } private void updateElementFields() { elementName = dialogR.getElementName(); minOccurs = dialogR.getMinOccurs(); maxOccurs = dialogR.getMaxOccurs(); superTypeName = dialogR.getSuperName(); isAbstract = dialogR.isAbstract(); typeName = dialogR.getTypeName(); isChoice = dialogR.isChoice(); isAll = dialogR.isAll(); } private boolean changeElementTypeToSequence() { if (selParticle != null) { XSDElementDeclaration elem = (XSDElementDeclaration) selParticle.getContent(); if (Util.changeElementTypeToSequence(elem, maxOccurs) == Status.CANCEL_STATUS) { return false; } } return true; } private boolean createComplexTypeParticle() { try { XSDParticle particle = createParticle(); boolean flag = transformToComplexType(particle); if (!flag) { modelGroup.getContents().remove(particle); return false; } page.refresh(); page.getTreeViewer().setSelection(new StructuredSelection(particle), true); page.markDirty(); } catch (Exception e) { log.error(e.getMessage(), e); MessageDialog.openError(page.getSite().getShell(), Messages._Error, Messages.bind(Messages._CreateCTypeError, e.getLocalizedMessage())); return false; } return true; } private XSDParticle createParticle() { XSDFactory factory = XSDSchemaBuildingTools.getXSDFactory(); XSDElementDeclaration resultElementDeclaration = factory.createXSDElementDeclaration(); resultElementDeclaration.setName(elementName); resultElementDeclaration.setTypeDefinition(schema.resolveSimpleTypeDefinition(schema.getSchemaForSchemaNamespace(), defaultTypeName)); XSDParticle resultParticle = factory.createXSDParticle(); resultParticle.setContent(resultElementDeclaration); resultParticle.setMinOccurs(this.minOccurs); XSDModelGroup group = modelGroup; if (maxOccurs > -1) { resultParticle.setMaxOccurs(this.maxOccurs); group.getContents().add(group.getContents().size(), resultParticle); group.updateElement(); } else { resultParticle.setMaxOccurs(this.maxOccurs); group.getContents().add(group.getContents().size(), resultParticle); group.updateElement(); if (resultParticle.getElement().getAttributeNode("maxOccurs") != null) { //$NON-NLS-1$ resultParticle.getElement().getAttributeNode("maxOccurs").setNodeValue("unbounded");//$NON-NLS-1$//$NON-NLS-2$ } else { resultParticle.getElement().setAttribute("maxOccurs", "unbounded");//$NON-NLS-1$//$NON-NLS-2$ } } Util.changeElementTypeToSequence(resultElementDeclaration, maxOccurs); if (dialogR.isInherit()) { XSDTerm totm = resultParticle.getTerm(); XSDElementDeclaration concept = null; Object parent = Util.getParent(resultParticle); if (parent instanceof XSDElementDeclaration) { concept = (XSDElementDeclaration) parent; } else { concept = (XSDElementDeclaration) resultParticle.getContent(); } XSDAnnotation fromannotation = null; if (concept != null) { fromannotation = concept.getAnnotation(); } if (fromannotation != null) { XSDAnnotationsStructure struc = new XSDAnnotationsStructure(totm); if (((XSDElementDeclaration) totm).getType() != null) { addAnnotion(struc, fromannotation); } } } return resultParticle; } public void addAnnotion(XSDAnnotationsStructure struc, XSDAnnotation xsdannotationparent) { Map<String, List<String>> infor = new HashMap<String, List<String>>(); infor = cloneXSDAnnotation(xsdannotationparent); Set<String> keys = infor.keySet(); for (int i = 0; i < infor.size(); i++) { List<String> lists = infor.get(keys.toArray()[i]); try { struc.setAccessRole(lists, false, (IStructuredContentProvider) page.getTreeViewer().getContentProvider(), (String) keys.toArray()[i]); } catch (Exception e) { log.error(e.getMessage(), e); } } } public Map<String, List<String>> cloneXSDAnnotation(XSDAnnotation oldAnn) { Map<String, List<String>> infor = new HashMap<String, List<String>>(); try { if (oldAnn != null) { for (int i = 0; i < oldAnn.getApplicationInformation().size(); i++) { Element oldElem = oldAnn.getApplicationInformation().get(i); String type = oldElem.getAttributes().getNamedItem("source").getNodeValue(); //$NON-NLS-1$ // X_Write,X_Hide,X_Workflow if (type.equals("X_Write") || type.equals("X_Hide") || type.equals("X_Workflow")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ if (!infor.containsKey(type)) { List<String> typeList = new ArrayList<String>(); typeList.add(oldElem.getFirstChild().getNodeValue()); infor.put(type, typeList); } else { (infor.get(type)).add(oldElem.getFirstChild().getNodeValue()); } } } } } catch (Exception e) { log.error(e.getMessage(), e); MessageDialog.openError(this.page.getSite().getShell(), Messages._Error, Messages.bind(Messages._PasteError, e.getLocalizedMessage())); } return infor; } private boolean transformToComplexType(XSDParticle particle) { XSDElementDeclaration decl = (XSDElementDeclaration) particle.getContent(); List<XSDComplexTypeDefinition> types = Util.getComplexTypes(schema); XSDFactory factory = XSDSchemaBuildingTools.getXSDFactory(); boolean anonymous = (typeName == null) || ("".equals(typeName));//$NON-NLS-1$ boolean alreadyExists = false; XSDComplexTypeDefinition complexType = null; // the sub element created if needed XSDParticle subParticle = null; XSDParticle groupParticle = null; XSDElementDeclaration subElement = null; XSDElementDeclaration parent = null; Object pObject = Util.getParent(decl); if (pObject instanceof XSDElementDeclaration) { parent = (XSDElementDeclaration) pObject; } if (!anonymous) { if (typeName.lastIndexOf(" : ") != -1) {//$NON-NLS-1$ typeName = typeName.substring(0, typeName.lastIndexOf(" : "));//$NON-NLS-1$ } for (XSDComplexTypeDefinition td : types) { if ((td.getName().equals(typeName))) { alreadyExists = true; complexType = td; break; } } } else { if (decl.getTypeDefinition() instanceof XSDSimpleTypeDefinition) { alreadyExists = false; } } if (alreadyExists) { XSDParticle partCnt = (XSDParticle) complexType.getContentType(); partCnt.unsetMaxOccurs(); partCnt.unsetMinOccurs(); XSDTypeDefinition superType = null; for (XSDTypeDefinition type : types) { if (type.getName().equals(superTypeName)) { superType = type; break; } } if (superType != null) { XSDModelGroup mdlGrp = (XSDModelGroup) partCnt.getTerm(); boolean status = updateCompositorType(superType, mdlGrp); if (!status) { return false; } complexType.setDerivationMethod(XSDDerivationMethod.EXTENSION_LITERAL); complexType.setBaseTypeDefinition(superType); } if (isAbstract) { complexType.setAbstract(isAbstract); } else { complexType.unsetAbstract(); } if (parent != null) { parent.updateElement(); } if (complexType != null) { complexType.updateElement(); } } else {// Create if does not exist // add an element declaration subElement = factory.createXSDElementDeclaration(); subElement.setName("subelement");//$NON-NLS-1$ subElement .setTypeDefinition(schema.resolveSimpleTypeDefinition(schema.getSchemaForSchemaNamespace(), defaultTypeName)); subParticle = factory.createXSDParticle(); subParticle.unsetMaxOccurs(); subParticle.unsetMinOccurs(); subParticle.setContent(subElement); subParticle.updateElement(); // create group XSDModelGroup group = factory.createXSDModelGroup(); if (isChoice) { group.setCompositor(XSDCompositor.CHOICE_LITERAL); } else if (isAll) { group.setCompositor(XSDCompositor.ALL_LITERAL); } else { group.setCompositor(XSDCompositor.SEQUENCE_LITERAL); } group.getContents().add(0, subParticle); group.updateElement(); // create the complex type complexType = factory.createXSDComplexTypeDefinition(); // complexType.setDerivationMethod(XSDDerivationMethod.EXTENSION_LITERAL); if (!anonymous) { // if (true) { XSDTypeDefinition superType = null; for (XSDTypeDefinition type : types) { if (type.getName().equals(superTypeName)) { superType = type; break; } } complexType.setName(typeName); if (superType != null) { boolean status = updateCompositorType(superType, group); if (!status) { return false; } complexType.setDerivationMethod(XSDDerivationMethod.EXTENSION_LITERAL); complexType.setBaseTypeDefinition(superType); } if (isAbstract) { complexType.setAbstract(isAbstract); } else { complexType.unsetAbstract(); } schema.getContents().add(complexType); } complexType.updateElement(); // add the group groupParticle = factory.createXSDParticle(); groupParticle.unsetMaxOccurs(); groupParticle.unsetMinOccurs(); groupParticle.setContent(group); groupParticle.updateElement(); complexType.setContent(groupParticle); complexType.updateElement(); }// end if NOT already exusts // set complex type to concept if (anonymous) { decl.setAnonymousTypeDefinition(complexType); } else { decl.setTypeDefinition(complexType); } decl.updateElement(); schema.update(); return true; } private boolean updateCompositorType(XSDTypeDefinition superType, XSDModelGroup currentGroup) { XSDParticle superTypeParticle = superType.getComplexType(); XSDTerm term = superTypeParticle.getTerm(); if (term instanceof XSDModelGroup) { XSDModelGroup group = (XSDModelGroup) term; if (group.getCompositor() == XSDCompositor.ALL_LITERAL || currentGroup.getCompositor() == XSDCompositor.ALL_LITERAL) { if (MessageDialog.openConfirm(null, Messages._ChangeToSequenceType, Messages._ComplexTypeToSequence)) { group.setCompositor(XSDCompositor.SEQUENCE_LITERAL); superTypeParticle.updateElement(); currentGroup.setCompositor(XSDCompositor.SEQUENCE_LITERAL); currentGroup.updateElement(); return true; } return false; } } return true; } }