/*******************************************************************************
* 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.validation.constraints;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.xml.namespace.QName;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.validation.IValidationContext;
import org.eclipse.emf.validation.model.ConstraintStatus;
import org.eclipse.wst.sse.sieditor.model.i18n.Messages;
import org.eclipse.wst.wsdl.Binding;
import org.eclipse.wst.wsdl.Definition;
import org.eclipse.wst.wsdl.Import;
import org.eclipse.wst.wsdl.Message;
import org.eclipse.wst.wsdl.PortType;
import org.eclipse.wst.wsdl.Service;
import org.eclipse.wst.wsdl.WSDLElement;
import org.eclipse.wst.wsdl.WSDLPackage;
public class KeyAttribute extends AbstractConstraint {
@Override
protected IStatus doValidate(IValidationContext ctx) {
ConstraintData[] constraintData = getConstraintData(ctx.getTarget());
List<IStatus> statusList = new ArrayList<IStatus>();
for (ConstraintData data : constraintData) {
statusList.addAll(data.validate(ctx));
}
return createStatus(ctx, statusList);
}
@Override
protected boolean shouldExecute(IValidationContext ctx) {
EObject target = ctx.getTarget();
if (target instanceof Definition) {
return isBatchValidation(ctx);
}
return isLiveValidation(ctx);
}
private ConstraintData[] getConstraintData(EObject target) {
WSDLElement element = (WSDLElement) target;
if (element instanceof Definition) {
return new ConstraintData[] {
new ConstraintData(element, WSDLPackage.DEFINITION__EMESSAGES, WSDLPackage.Literals.MESSAGE__QNAME),
new ConstraintData(element, WSDLPackage.DEFINITION__EPORT_TYPES, WSDLPackage.Literals.PORT_TYPE__QNAME),
new ConstraintData(element, WSDLPackage.DEFINITION__EBINDINGS, WSDLPackage.Literals.BINDING__QNAME),
new ConstraintData(element, WSDLPackage.DEFINITION__ESERVICES, WSDLPackage.Literals.SERVICE__QNAME),
new ConstraintData(element, WSDLPackage.DEFINITION__EIMPORTS, WSDLPackage.Literals.IMPORT__NAMESPACE_URI) };
} else {
if (element.eContainer() == null) {
// inner elements with null container are deleted and should not be processed
return new ConstraintData[] {};
}
if (element instanceof Message) {
return new ConstraintData[] { new ConstraintData(element.getContainer(), WSDLPackage.DEFINITION__EMESSAGES,
WSDLPackage.Literals.MESSAGE__QNAME) };
} else if (element instanceof PortType) {
return new ConstraintData[] { new ConstraintData(element.getContainer(), WSDLPackage.DEFINITION__EPORT_TYPES,
WSDLPackage.Literals.PORT_TYPE__QNAME) };
} else if (element instanceof Binding) {
return new ConstraintData[] { new ConstraintData(element.getContainer(), WSDLPackage.DEFINITION__EBINDINGS,
WSDLPackage.Literals.BINDING__QNAME) };
} else if (element instanceof Service) {
return new ConstraintData[] { new ConstraintData(element.getContainer(), WSDLPackage.DEFINITION__ESERVICES,
WSDLPackage.Literals.SERVICE__QNAME) };
} else if (element instanceof Import) {
return new ConstraintData[] { new ConstraintData(element.getContainer(), WSDLPackage.DEFINITION__EIMPORTS,
WSDLPackage.Literals.IMPORT__NAMESPACE_URI) };
}
}
throw new IllegalArgumentException();
}
private static class ConstraintData {
private WSDLElement parent;
private EStructuralFeature collectionFeature;
private EStructuralFeature keyFeature;
public ConstraintData(WSDLElement parent, int collectionFeatureId, EStructuralFeature keyFeature) {
this.parent = parent;
collectionFeature = parent.eClass().getEStructuralFeature(collectionFeatureId);
this.keyFeature = keyFeature;
}
@SuppressWarnings("unchecked")
public List<IStatus> validate(IValidationContext ctx) {
Set<Object> allKeys = new HashSet<Object>();
EList<WSDLElement> collection = (EList<WSDLElement>) parent.eGet(collectionFeature);
List<IStatus> statusList = new ArrayList<IStatus>(collection.size());
// the location of the error will be the name
Collection<EObject> locus = new ArrayList<EObject>();
locus.add(this.keyFeature);
final Set<Object> duplicateKeys = new HashSet<Object>();
for (WSDLElement element : collection) {
Object key = element.eGet(keyFeature);
IStatus status = null;
if (allKeys.contains(key)) {
duplicateKeys.add(key);
status = ConstraintStatus.createStatus(ctx, element, locus, Messages.DuplicateKey, getKeyName(key), parent
.getElement().getLocalName(), element.getElement().getLocalName());
} else {
allKeys.add(key);
status = ConstraintStatus.createSuccessStatus(ctx, element, null);
}
statusList.add(status);
}
// adds the first elements to the status list
for (int i = 0; i < collection.size(); i++) {
final WSDLElement element = collection.get(i);
final Object key = element.eGet(keyFeature);
if (duplicateKeys.contains(key)) {
duplicateKeys.remove(key);
ConstraintStatus errorStatus = ConstraintStatus.createStatus(ctx, element, locus, Messages.DuplicateKey,
getKeyName(key), parent.getElement().getLocalName(), element.getElement().getLocalName());
statusList.set(i, errorStatus);
}
}
return statusList;
}
private static String getKeyName(Object key) {
if (key instanceof QName) {
return ((QName) key).getLocalPart();
} else if (key instanceof String) {
return (String) key;
} else {
throw new IllegalArgumentException();
}
}
}
}