// ============================================================================
//
// 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.HashSet;
import java.util.Iterator;
import java.util.List;
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.emf.common.util.EList;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Event;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDFactory;
import org.eclipse.xsd.XSDIdentityConstraintDefinition;
import org.eclipse.xsd.XSDModelGroup;
import org.eclipse.xsd.XSDParticle;
import org.eclipse.xsd.XSDSimpleTypeDefinition;
import org.eclipse.xsd.XSDXPathDefinition;
import org.eclipse.xsd.util.XSDConstants;
import org.eclipse.xsd.util.XSDSchemaBuildingTools;
import org.w3c.dom.Element;
import com.amalto.workbench.dialogs.BusinessElementInputDialog;
import com.amalto.workbench.editors.DataModelMainPage;
import com.amalto.workbench.i18n.Messages;
import com.amalto.workbench.image.EImage;
import com.amalto.workbench.image.ImageCache;
import com.amalto.workbench.providers.datamodel.SchemaTreeContentProvider;
import com.amalto.workbench.utils.IConstants;
import com.amalto.workbench.utils.Util;
public class XSDEditParticleAction extends UndoAction implements SelectionListener {
private static Log log = LogFactory.getLog(XSDEditParticleAction.class);
private BusinessElementInputDialog dialog = null;
private XSDParticle selParticle = null;
private String elementName;
private String refName;
private int minOccurs;
private int maxOccurs;
private String initEleName = ""; //$NON-NLS-1$
public XSDEditParticleAction(DataModelMainPage page) {
super(page);
setImageDescriptor(ImageCache.getImage(EImage.EDIT_OBJ.getPath()));
setText(Messages.XSDEditParticleAction_EditElement);
setToolTipText(Messages.XSDEditParticleAction_EditBusinessElement);
}
@Override
public IStatus doAction() {
try {
IStructuredSelection selection = (IStructuredSelection) page.getTreeViewer().getSelection();
String originalXpath = getOriginalXpath();
String entity = originalXpath.substring(0, originalXpath.indexOf("/")); //$NON-NLS-1$
selParticle = (XSDParticle) selection.getFirstElement();
if (!(selParticle.getTerm() instanceof XSDElementDeclaration)) {
return Status.CANCEL_STATUS;
}
XSDElementDeclaration decl = (XSDElementDeclaration) selParticle.getContent();
XSDElementDeclaration ref = null;
if (decl.isElementDeclarationReference()) {
// it is a ref
ref = decl.getResolvedElementDeclaration();
}
EList eDecls = decl.getSchema().getElementDeclarations();
ArrayList<String> elementDeclarations = new ArrayList<String>();
for (Iterator iter = eDecls.iterator(); iter.hasNext();) {
XSDElementDeclaration d = (XSDElementDeclaration) iter.next();
if (d.getTargetNamespace() != null && d.getTargetNamespace().equals(IConstants.DEFAULT_NAME_SPACE)) {
continue;
}
if (!d.getQName().equals(entity)) {
elementDeclarations
.add(d.getQName() + (d.getTargetNamespace() != null ? " : " + d.getTargetNamespace() : "")); //$NON-NLS-1$ //$NON-NLS-2$
}
}
elementDeclarations.add(""); //$NON-NLS-1$
XSDIdentityConstraintDefinition identify = null;
XSDXPathDefinition keyPath = null;
List<Object> keyInfo = Util.getKeyInfo(decl);
boolean isPK = false;
if (keyInfo != null && keyInfo.size() > 0) {
identify = (XSDIdentityConstraintDefinition) keyInfo.get(0);
keyPath = (XSDXPathDefinition) keyInfo.get(1);
isPK = true;
}
initEleName = decl.getName();
dialog = new BusinessElementInputDialog(this, page.getSite().getShell(), Messages.XSDEditParticleAction_InputDialogTitle, decl.getName(),
ref == null ? null : ref.getQName(), elementDeclarations, selParticle.getMinOccurs(),
selParticle.getMaxOccurs(), false, isPK);
dialog.setBlockOnOpen(true);
int ret = dialog.open();
if (ret == Window.CANCEL) {
return Status.CANCEL_STATUS;
}
if (keyPath != null) {
identify.getFields().remove(keyPath);
}
// find reference
XSDElementDeclaration newRef = null;
if (!"".equals(refName.trim())) { //$NON-NLS-1$
newRef = Util.findReference(refName, schema);
if (newRef == null) {
MessageDialog.openError(this.page.getSite().getShell(), Messages._Error, Messages.bind(Messages.XSDEditParticleAction_ErrorMsg, refName));
return Status.CANCEL_STATUS;
}
}// ref
decl.setName("".equals(this.elementName) ? null : this.elementName); //$NON-NLS-1$
if (keyPath != null) {
XSDFactory factory = XSDSchemaBuildingTools.getXSDFactory();
XSDXPathDefinition field = factory.createXSDXPathDefinition();
field.setVariety(keyPath.getVariety());
field.setValue(elementName);
identify.getFields().add(field);
}
if (newRef != null) {
decl.setResolvedElementDeclaration(newRef);
decl.setTypeDefinition(null);
Element elem = decl.getElement();
if (elem.getAttributes().getNamedItem("type") != null)
{
elem.getAttributes().removeNamedItem("type");//$NON-NLS-1$
}
decl.updateElement();
} else if (ref != null) {
// fliu
// no more element declarations --> we create a new Declaration with String simpleType definition
// instead
// FIXME: dereferecning and element is buggy
XSDFactory factory = XSDSchemaBuildingTools.getXSDFactory();
XSDElementDeclaration newD = factory.createXSDElementDeclaration();
newD.setName(this.elementName);
newD.updateElement();
XSDSimpleTypeDefinition stringType = ((SchemaTreeContentProvider) page.getTreeViewer().getContentProvider())
.getXsdSchema().getSchemaForSchema()
.resolveSimpleTypeDefinition(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001, "string"); //$NON-NLS-1$
newD.setTypeDefinition(stringType);
if (selParticle.getContainer() instanceof XSDModelGroup) {
XSDModelGroup group = ((XSDModelGroup) selParticle.getContainer());
((XSDModelGroup) selParticle.getContainer()).getContents().remove(selParticle);
selParticle = factory.createXSDParticle();
selParticle.setContent(newD);
group.getContents().add(selParticle);
}
}
if (Util.changeElementTypeToSequence(decl, maxOccurs) == Status.CANCEL_STATUS) {
return Status.CANCEL_STATUS;
}
selParticle.setMinOccurs(this.minOccurs);
if (maxOccurs > -1) {
selParticle.setMaxOccurs(this.maxOccurs);
} else {
if (selParticle.getElement().getAttributeNode("maxOccurs") != null) {
selParticle.getElement().getAttributeNode("maxOccurs").setNodeValue("unbounded");//$NON-NLS-1$//$NON-NLS-2$
} else {
selParticle.getElement().setAttribute("maxOccurs", "unbounded");//$NON-NLS-1$//$NON-NLS-2$
}
}
selParticle.updateElement();
updateReference(originalXpath);
page.refresh();
page.markDirty();
} catch (Exception e) {
log.error(e.getMessage(), e);
MessageDialog.openError(page.getSite().getShell(), Messages._Error, Messages.bind(Messages.XSDEditParticleAction_ErrorMsg1
, e.getLocalizedMessage()));
return Status.CANCEL_STATUS;
}
return Status.OK_STATUS;
}
private String getOriginalXpath() {
XSDGetXPathAction getXpathAction = new XSDGetXPathAction(page);
getXpathAction.doAction();
String originalXpath = getXpathAction.getCopiedXpath();
return originalXpath;
}
private void updateReference(String originalXpath) {
XSDElementDeclaration decl = (XSDElementDeclaration) selParticle.getContent();
int lastIndex = originalXpath.lastIndexOf("/"); //$NON-NLS-1$
String newXpath = decl.getName();
newXpath = originalXpath.substring(0, lastIndex + 1) + newXpath;
IStructuredContentProvider provider = (IStructuredContentProvider) page.getTreeViewer().getContentProvider();
Object[] allForeignKeyRelatedInfos = Util.getAllForeignKeyRelatedInfos(page.getSite(), new ArrayList<Object>(), provider,
new HashSet<Object>());
Util.updateForeignKeyRelatedInfo(originalXpath, newXpath, allForeignKeyRelatedInfos);
}
@Override
public void runWithEvent(Event event) {
super.runWithEvent(event);
}
/********************************
* Listener to input dialog
*/
public void widgetDefaultSelected(SelectionEvent e) {
}
public void widgetSelected(SelectionEvent e) {
if (dialog.getReturnCode() == -1)
{
return; // there was a validation error
}
elementName = dialog.getElementName();
refName = dialog.getRefName();
minOccurs = dialog.getMinOccurs();
maxOccurs = dialog.getMaxOccurs();
// check that this element does not already exist
XSDModelGroup group = (XSDModelGroup) selParticle.getContainer();
// get position of the selected particle in the container
for (Iterator iter = group.getContents().iterator(); iter.hasNext();) {
XSDParticle p = (XSDParticle) iter.next();
if (p.getTerm() instanceof XSDElementDeclaration) {
XSDElementDeclaration thisDecl = (XSDElementDeclaration) p.getTerm();
if (thisDecl.getName().equals(elementName) && initEleName != null && !initEleName.equalsIgnoreCase(elementName)) {
MessageDialog.openError(page.getSite().getShell(), Messages._Error, Messages.bind(Messages.XSDEditParticleAction_ErrorMsg2, elementName));
return;
}
}
}// for
dialog.close();
}
}