/*******************************************************************************
* Copyright (c) 2010 SAP AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Emil Simeonov - initial API and implementation.
* Dimitar Donchev - initial API and implementation.
* Dimitar Tenev - initial API and implementation.
* Nevena Manova - initial API and implementation.
* Georgi Konstantinov - initial API and implementation.
* Keshav Veerapaneni - initial API and implementation.
*******************************************************************************/
package org.eclipse.wst.sse.sieditor.command.emf.xsd;
import java.util.List;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.xsd.XSDAnnotation;
import org.eclipse.xsd.XSDAttributeDeclaration;
import org.eclipse.xsd.XSDConcreteComponent;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDParticle;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.XSDSimpleTypeDefinition;
import org.eclipse.xsd.XSDTypeDefinition;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import org.eclipse.wst.sse.sieditor.command.common.AbstractNotificationOperation;
import org.eclipse.wst.sse.sieditor.model.api.IModelObject;
import org.eclipse.wst.sse.sieditor.model.api.IModelRoot;
import org.eclipse.wst.sse.sieditor.model.api.IXSDModelRoot;
import org.eclipse.wst.sse.sieditor.model.i18n.Messages;
import org.eclipse.wst.sse.sieditor.model.utils.StatusUtils;
import org.eclipse.wst.sse.sieditor.model.xsd.impl.AbstractXSDComponent;
import org.eclipse.wst.sse.sieditor.model.xsd.impl.Schema;
import org.eclipse.wst.sse.sieditor.model.xsd.impl.SimpleType;
import org.eclipse.wst.sse.sieditor.model.xsd.impl.StructureType;
/**
* Updates documentation for XSD Components
*
*
*/
public class SetDocumentationCommand extends AbstractNotificationOperation {
private static final String DOCU_ELEMENT_TAG = "documentation"; //$NON-NLS-1$
private final String _text;
private Element _documentationElement;
private boolean _isNew;
private IStatus lastAddAnnotationCommandStatus = Status.CANCEL_STATUS;
public SetDocumentationCommand(final IModelRoot root, final IModelObject modelObject, final String text) {
super(root, modelObject, Messages.SetDocumentationCommand_set_documentation_command_label);
this._text = text;
}
@Override
public IStatus run(IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
lastAddAnnotationCommandStatus = Status.CANCEL_STATUS;
XSDAnnotation annotation = getDocumentationAnnotation(modelObject);
if (annotation == null) {
return lastAddAnnotationCommandStatus;
}
// this command only ensures that the text is inserted as the first
// userinfo in the documentation and it only considers the first text
// after the documentation element for inserting the text
final List<Element> userInfo = annotation.getUserInformation();
final Element annotationElement = annotation.getElement();
final Document document = annotationElement.getOwnerDocument();
if (userInfo.size() == 0) {
// Have to ensure the documentation element since the EMF doesn't
// include
// userinfo and appinfo as part of model and is included in the DOM
// for documentation
final Node firstChild = annotationElement.getFirstChild();
final String prefix = annotationElement.getPrefix();
_documentationElement = (prefix != null && prefix.length() > 0) ? document.createElement(prefix
+ ":" + DOCU_ELEMENT_TAG) : //$NON-NLS-1$
document.createElement(DOCU_ELEMENT_TAG);
if (firstChild == null)
annotationElement.appendChild(_documentationElement);
else
annotationElement.insertBefore(_documentationElement, firstChild);
_isNew = true;
} else {
_documentationElement = userInfo.get(0);
}
final Node textNode = _documentationElement.getFirstChild();
if (textNode != null) {
if (textNode instanceof Text)
textNode.setNodeValue(_text);
else {
org.w3c.dom.Text newTextNode = document.createTextNode(_text);
_documentationElement.insertBefore(newTextNode, textNode);
}
} else {
if (_text.length() > 0) {
org.w3c.dom.Text newTextNode = document.createTextNode(_text);
_documentationElement.appendChild(newTextNode);
}
}
if (_isNew)
annotation.getUserInformation().add(_documentationElement);
return Status.OK_STATUS;
}
public boolean canExecute() {
return _text != null;
}
public Element getDocumentationElement() {
return _documentationElement;
}
public boolean isNewElement() {
return _isNew;
}
private XSDAnnotation getDocumentationAnnotation(IModelObject modelObject) throws ExecutionException {
if (modelObject instanceof org.eclipse.wst.sse.sieditor.model.xsd.impl.Element) {
return getElementDocumentationAnnotation((AbstractXSDComponent) modelObject);
} else if (modelObject instanceof SimpleType) {
return getSimpleTypeDocumentationAnnotation((SimpleType) modelObject);
} else if (modelObject instanceof StructureType) {
return getStructureTypeDocumentationAnnotation((StructureType) modelObject);
} else if (modelObject instanceof Schema) {
return getSchemaDocumentationAnnotation((Schema) modelObject);
}
return null;
}
private XSDAnnotation getSchemaDocumentationAnnotation(Schema schema) throws ExecutionException {
XSDSchema component = schema.getComponent();
final List<XSDAnnotation> annotations = component.getAnnotations();
XSDAnnotation annotation = null;
if (annotations.size() > 0) {
annotation = annotations.get(0);
} else {
annotation = executeAddAnnotationCommand(component, schema.getModelRoot(), schema);
}
return annotation;
}
private XSDAnnotation getElementDocumentationAnnotation(AbstractXSDComponent modelObject) throws ExecutionException {
XSDConcreteComponent component = modelObject.getComponent();
XSDAnnotation annotation = null;
if (component instanceof XSDParticle) {
XSDElementDeclaration element = (XSDElementDeclaration) ((XSDParticle) component).getContent();
annotation = element.getAnnotation();
if (null == annotation) {
annotation = executeAddAnnotationCommand(element, modelObject.getModelRoot(), modelObject);
}
} else if (component instanceof XSDAttributeDeclaration) {
XSDAttributeDeclaration attribute = (XSDAttributeDeclaration) component;
annotation = attribute.getAnnotation();
if (null == annotation) {
annotation = executeAddAnnotationCommand(attribute, modelObject.getModelRoot(), modelObject);
}
}
return annotation;
}
private XSDAnnotation getSimpleTypeDocumentationAnnotation(SimpleType simpleType) throws ExecutionException {
XSDSimpleTypeDefinition component = (XSDSimpleTypeDefinition) simpleType.getComponent();
XSDAnnotation annotation = component.getAnnotation();
if (annotation == null) {
annotation = executeAddAnnotationCommand(component, ((Schema) simpleType.getParent()).getModelRoot(), simpleType);
}
return annotation;
}
private XSDAnnotation getStructureTypeDocumentationAnnotation(StructureType structureType) throws ExecutionException {
XSDElementDeclaration element = structureType.getElement();
XSDAnnotation annotation = null;
if (element != null) {
annotation = element.getAnnotation();
if (null == annotation) {
annotation = executeAddAnnotationCommand(element, ((Schema) structureType.getParent()).getModelRoot(), structureType);
}
} else {
XSDTypeDefinition xsdTypeDefinition = structureType.getXSDTypeDefinition();
if (xsdTypeDefinition != null) {
annotation = xsdTypeDefinition.getAnnotation();
if (null == annotation) {
annotation = executeAddAnnotationCommand(xsdTypeDefinition, ((Schema) structureType.getParent()).getModelRoot(), structureType);
}
}
}
return annotation;
}
private XSDAnnotation executeAddAnnotationCommand(Object targetObject, IXSDModelRoot root, IModelObject object) throws ExecutionException {
AddAnotationCommand command = new AddAnotationCommand(targetObject, root, object);
lastAddAnnotationCommandStatus = getModelRoot().getEnv().execute(command);
if (StatusUtils.canContinue(lastAddAnnotationCommandStatus)) {
return command.getAnnotation();
}
return null;
}
}