/*******************************************************************************
* 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.
*******************************************************************************/
package org.eclipse.wst.sse.sieditor.model.xsd.impl;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.xsd.XSDAnnotation;
import org.eclipse.xsd.XSDAttributeDeclaration;
import org.eclipse.xsd.XSDAttributeGroupContent;
import org.eclipse.xsd.XSDAttributeUse;
import org.eclipse.xsd.XSDAttributeUseCategory;
import org.eclipse.xsd.XSDComplexTypeDefinition;
import org.eclipse.xsd.XSDConcreteComponent;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDModelGroup;
import org.eclipse.xsd.XSDNamedComponent;
import org.eclipse.xsd.XSDParticle;
import org.eclipse.xsd.XSDParticleContent;
import org.eclipse.xsd.XSDSimpleTypeDefinition;
import org.eclipse.xsd.XSDTypeDefinition;
import org.eclipse.wst.sse.sieditor.command.emf.xsd.RenameElementCommand;
import org.eclipse.wst.sse.sieditor.command.emf.xsd.SetAnonymousCommand;
import org.eclipse.wst.sse.sieditor.command.emf.xsd.SetElementNillableCommand;
import org.eclipse.wst.sse.sieditor.command.emf.xsd.SetElementOccurences;
import org.eclipse.wst.sse.sieditor.command.emf.xsd.SetElementTypeCommand;
import org.eclipse.wst.sse.sieditor.core.common.Nil;
import org.eclipse.wst.sse.sieditor.model.api.IModelObject;
import org.eclipse.wst.sse.sieditor.model.api.IXSDModelRoot;
import org.eclipse.wst.sse.sieditor.model.generic.IllegalInputException;
import org.eclipse.wst.sse.sieditor.model.utils.EmfXsdUtils;
import org.eclipse.wst.sse.sieditor.model.xsd.api.IElement;
import org.eclipse.wst.sse.sieditor.model.xsd.api.IType;
public class Element extends AbstractXSDComponent implements IElement,
org.eclipse.wst.sse.sieditor.model.write.xsd.api.IElement {
private final XSDConcreteComponent _component;
private final XSDModelGroup _container;
private final IModelObject _parent;
private final Schema _schema;
public Element(final IXSDModelRoot modelRoot, final XSDConcreteComponent element, final XSDModelGroup container,
final IModelObject parent, final Schema schema) {
super(modelRoot);
Nil.checkNil(element, "element"); //$NON-NLS-1$
if (!(element instanceof XSDAttributeDeclaration))
Nil.checkNil(container, "container"); //$NON-NLS-1$
Nil.checkNil(parent, "parent"); //$NON-NLS-1$
Nil.checkNil(schema, "schema"); //$NON-NLS-1$
// Element can be one of XSDElementDeclaration or
// XSDAttributeDeclaration
if (!((element instanceof XSDParticle && ((XSDParticle) element).getContent() instanceof XSDElementDeclaration) || element instanceof XSDAttributeDeclaration)) {
throw new RuntimeException("element has to be one of XSDParticle or XSDAttributeDeclaration"); //$NON-NLS-1$
}
this._component = element;
this._container = container;
this._parent = parent;
this._schema = schema;
}
public String getNamespace() {
return _schema.getNamespace();
}
public int getMaxOccurs() {
if (_component instanceof XSDAttributeDeclaration) {
final XSDAttributeUseCategory use = ((XSDAttributeUse) _component.getContainer()).getUse();
// 1 if required
if (XSDAttributeUseCategory.PROHIBITED_LITERAL.equals(use))
return 0;
// 0 if attribute is prohibited or optional
return 1;
}
return ((XSDParticle) _component).getMaxOccurs();
}
public int getMinOccurs() {
if (_component instanceof XSDAttributeDeclaration) {
final XSDAttributeUseCategory use = ((XSDAttributeUse) _component.getContainer()).getUse();
// 1 if required
if (XSDAttributeUseCategory.REQUIRED_LITERAL.equals(use))
return 1;
// 0 if attribute is prohibited or optional
return 0;
}
return ((XSDParticle) _component).getMinOccurs();
}
public boolean getNillable() {
if (_component instanceof XSDAttributeDeclaration)
return false;
final XSDParticle particle = (XSDParticle) _component;
return ((XSDElementDeclaration) particle.getContent()).isNillable();
}
public IType getType() {
if (_component instanceof XSDAttributeDeclaration) {
final XSDAttributeDeclaration attribute = (XSDAttributeDeclaration) _component;
if (attribute.isAttributeDeclarationReference()) {
return null;
}
XSDSimpleTypeDefinition type = attribute.getAnonymousTypeDefinition();
if (null != type) {
// the type is anonymous
return new SimpleType(getModelRoot(), _schema, this, type);
}
type = attribute.getTypeDefinition();
return null == type ? null : (IType) _schema.resolveComponent(type, true);
} else if (_component instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle) _component;
if (!(particle.getContent() instanceof XSDElementDeclaration))
throw new RuntimeException("Element content should be XSDElementDeclaration");//$NON-NLS-1$
final XSDElementDeclaration element = (XSDElementDeclaration) particle.getContent();
if (element.isElementDeclarationReference()) {
final XSDElementDeclaration resolvedElement = element.getResolvedElementDeclaration();
return (AbstractType) (null == resolvedElement ? null : _schema.resolveComponent(resolvedElement, true));
}
XSDTypeDefinition type = element.getAnonymousTypeDefinition();
if (null != type) {
// the type is anonymous
if (type instanceof XSDComplexTypeDefinition) {
return new StructureType(getModelRoot(), _schema, this, type);
}
return new SimpleType(getModelRoot(), _schema, this, (XSDSimpleTypeDefinition) type);
}
type = element.getTypeDefinition();
return (IType) _schema.resolveComponent(type, true);
} else {
throw new RuntimeException("Component must be XSDElementDeclartion or XSDAttributeDeclaration"); //$NON-NLS-1$
}
}
public String getName() {
if (_component instanceof XSDAttributeDeclaration) {
final XSDAttributeDeclaration attribute = (XSDAttributeDeclaration) _component;
if (attribute.isAttributeDeclarationReference())
return null == attribute.getResolvedAttributeDeclaration() ? null : attribute.getResolvedAttributeDeclaration()
.getName();
return attribute.getName();
} else if (_component instanceof XSDParticle) {
final XSDElementDeclaration component = (XSDElementDeclaration) ((XSDParticle) _component).getContent();
if (component.isElementDeclarationReference())
return null == component.getResolvedElementDeclaration() ? null : component.getResolvedElementDeclaration()
.getName();
return component.getName();
} else
throw new RuntimeException("Component must be XSDElementDeclaration or XSDAttributeDeclaration"); //$NON-NLS-1$
}
public boolean isAttribute() {
return _component instanceof XSDAttributeDeclaration;
}
public String getDocumentation() {
final List<XSDAnnotation> annotations = new ArrayList<XSDAnnotation>(1);
final XSDAnnotation annotation;
if (_component instanceof XSDParticle) {
final XSDElementDeclaration content = (XSDElementDeclaration) ((XSDParticle) _component).getContent();
annotation = content.getAnnotation();
} else {
annotation = ((XSDAttributeDeclaration) _component).getAnnotation();
}
if (null != annotation)
annotations.add(annotation);
if (annotations.size() == 0)
return ""; //$NON-NLS-1$
final org.w3c.dom.Element documentation = getFirstElement(annotations);
return super.getDocumentation(documentation);
}
public IModelObject getParent() {
return _parent;
}
public IType setAnonymousType(final boolean isSimple) throws ExecutionException {
if (!isSimple && _component instanceof XSDAttributeDeclaration)
return null;
final SetAnonymousCommand command = new SetAnonymousCommand(getModelRoot(), this, (AbstractType) getType(), isSimple);
getModelRoot().getEnv().execute(command);
return command.getType();
}
public void setMaxOccurs(final int value) throws ExecutionException {
if (_component instanceof XSDParticle) {
final SetElementOccurences command = new SetElementOccurences(getModelRoot(), this, getMinOccurs(), value);
getModelRoot().getEnv().execute(command);
}
}
public void setMinOccurs(final int value) throws ExecutionException {
if (_component instanceof XSDParticle) {
final SetElementOccurences command = new SetElementOccurences(getModelRoot(), this, value, getMaxOccurs());
getModelRoot().getEnv().execute(command);
}
}
public void setNillable(final boolean nillable) throws ExecutionException {
if (_component instanceof XSDParticle) {
final XSDParticleContent content = ((XSDParticle) _component).getContent();
if (content instanceof XSDElementDeclaration) {
final SetElementNillableCommand command = new SetElementNillableCommand(getModelRoot(), this, nillable);
getModelRoot().getEnv().execute(command);
}
}
}
public void setType(final IType type) throws ExecutionException {
IType resolvedType = null;
if (type instanceof AbstractType)
resolvedType = _schema.resolveType((AbstractType) type);
// DOIT Import if needed
if (null != resolvedType) {
final SetElementTypeCommand command = new SetElementTypeCommand(getModelRoot(), this, resolvedType);
getModelRoot().getEnv().execute(command);
}
}
public void setName(final String name) throws IllegalInputException, ExecutionException {
Nil.checkNil(name, "name"); //$NON-NLS-1$
if (!EmfXsdUtils.isValidNCName(name))
throw new IllegalInputException("Entered Element name is not valid"); //$NON-NLS-1$
final RenameElementCommand cmd = new RenameElementCommand(getModelRoot(), this, name);
getModelRoot().getEnv().execute(cmd);
}
public void delete() {
if (_component instanceof XSDParticle) {
_container.getContents().remove(_component);
} else if (_component instanceof XSDAttributeDeclaration) {
if (_parent instanceof StructureType) {
final XSDNamedComponent component = (XSDNamedComponent) _parent.getComponent();
if (component instanceof XSDComplexTypeDefinition) {
for (final XSDAttributeGroupContent attrContent : new ArrayList<XSDAttributeGroupContent>(
((XSDComplexTypeDefinition) component).getAttributeContents())) {
if ((attrContent instanceof XSDAttributeUse)
&& _component.equals(((XSDAttributeUse) attrContent).getContent())) {
((XSDComplexTypeDefinition) component).getAttributeContents().remove(attrContent);
}
}
}
}
}
}
@Override
public XSDConcreteComponent getComponent() {
return _component;
}
public Schema getSchema() {
return _schema;
}
public XSDModelGroup getContainer() {
return _container;
}
}