/*******************************************************************************
* 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.text.MessageFormat;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.validation.IValidationContext;
import org.eclipse.emf.validation.model.ConstraintStatus;
import org.eclipse.wst.wsdl.Types;
import org.eclipse.wst.wsdl.XSDSchemaExtensibilityElement;
import org.eclipse.xsd.XSDAttributeDeclaration;
import org.eclipse.xsd.XSDComplexTypeDefinition;
import org.eclipse.xsd.XSDConcreteComponent;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDNamedComponent;
import org.eclipse.xsd.XSDPackage;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.XSDTypeDefinition;
import org.eclipse.xsd.util.XSDConstants;
import org.eclipse.wst.sse.sieditor.model.i18n.Messages;
import org.eclipse.wst.sse.sieditor.model.reconcile.utils.ObjectsForResolveContainer;
import org.eclipse.wst.sse.sieditor.model.reconcile.utils.ObjectsForResolveUtils;
import org.eclipse.wst.sse.sieditor.model.reconcile.utils.componentresolver.BaseComponentResolver;
import org.eclipse.wst.sse.sieditor.model.reconcile.utils.componentresolver.XsdComplexTypeDefinitionExtensionResolver;
public class UnresolvedXsdContentsValidation extends AbstractConstraint {
@Override
protected IStatus doValidate(final IValidationContext ctx) {
final List<XSDSchema> allSchemas = getAllContainedSchemas(((XSDConcreteComponent) ctx.getTarget()).getSchema());
final List<IStatus> statusList = new LinkedList<IStatus>();
for (final XSDSchema schema : allSchemas) {
final ObjectsForResolveContainer container = ObjectsForResolveUtils.instance().findObjectsForResolve(schema,
allSchemas);
validateElementReferences(ctx, container.getElementsForReferenceResolve(), statusList);
validateElementTypeDefinitions(ctx, container.getElementsForTypeResolve(), statusList);
validateAttributeTypeDefinitions(ctx, container.getAttributesForTypeResolve(), statusList);
validateAttributeReferences(ctx, container.getAttributesForReferenceResolve(), statusList);
validateComplexTypeDefinitions(ctx, container.getComplexTypesForExtensionResolve(), statusList,
XSDConstants.EXTENSION_ELEMENT_TAG);
validateComplexTypeDefinitions(ctx, container.getComplexTypesForRestrictionResolve(), statusList,
XSDConstants.RESTRICTION_ELEMENT_TAG);
}
return createStatus(ctx, statusList);
}
@SuppressWarnings("unchecked")
private List<XSDSchema> getAllContainedSchemas(final XSDSchema schema) {
final List<XSDSchema> allSchemas = new LinkedList<XSDSchema>();
if (schema != null && schema.eContainer() == null) {
allSchemas.add(schema);
} else if (schema != null && schema.eContainer() instanceof XSDSchemaExtensibilityElement) {
final Types eTypes = ((XSDSchemaExtensibilityElement) schema.eContainer()).getEnclosingDefinition().getETypes();
if (eTypes != null) {
allSchemas.addAll(eTypes.getSchemas());
}
}
return allSchemas;
}
private void validateElementReferences(final IValidationContext ctx,
final List<XSDNamedComponent> elementsForReferenceResolve, final List<IStatus> statusList) {
for (final XSDNamedComponent xsdElementDeclaration : elementsForReferenceResolve) {
final XSDElementDeclaration resolvedElementDeclaration = ((XSDElementDeclaration) xsdElementDeclaration)
.getResolvedElementDeclaration();
if (resolvedElementDeclaration.eContainer() == null) {
continue;
}
final Set<EObject> resultLocus = new HashSet<EObject>();
resultLocus.add(XSDPackage.Literals.XSD_ELEMENT_DECLARATION__ELEMENT_DECLARATION_REFERENCE);
statusList.add(ConstraintStatus.createStatus(ctx, xsdElementDeclaration, resultLocus, MessageFormat.format(
Messages.UnresolvedXsdContentsValidation_element_reference_X_Y_is_unresolved_msg, resolvedElementDeclaration
.getTargetNamespace(), resolvedElementDeclaration.getName()), IStatus.ERROR));
}
}
private void validateElementTypeDefinitions(final IValidationContext ctx,
final List<XSDNamedComponent> elementsForTypeResolve, final List<IStatus> statusList) {
final EReference locusFeature = XSDPackage.Literals.XSD_ELEMENT_DECLARATION__TYPE_DEFINITION;
for (final XSDNamedComponent namedComponent : elementsForTypeResolve) {
final XSDTypeDefinition typeDefinition = getTypeDefinition(namedComponent);
final String typeDefinitionName = BaseComponentResolver.getResolveComponentLocalName(namedComponent.getElement(),
typeDefinition);
if (typeDefinitionName == null) {
continue;
}
final Set<EObject> resultLocus = new HashSet<EObject>();
resultLocus.add(locusFeature);
statusList.add(ConstraintStatus.createStatus(ctx, namedComponent, resultLocus, MessageFormat.format(
Messages.UnresolvedXsdContentsValidation_type_reference_X_Y_is_unresolved_validation_msg, typeDefinition
.getTargetNamespace(), typeDefinitionName), IStatus.ERROR));
}
}
private void validateAttributeTypeDefinitions(final IValidationContext ctx,
final List<XSDNamedComponent> attributesForTypeResolve, final List<IStatus> statusList) {
final EReference locusFeature = XSDPackage.Literals.XSD_ATTRIBUTE_DECLARATION__TYPE_DEFINITION;
for (final XSDNamedComponent namedComponent : attributesForTypeResolve) {
final XSDTypeDefinition typeDefinition = getTypeDefinition(namedComponent);
final String typeDefinitionName = BaseComponentResolver.getResolveComponentLocalName(namedComponent.getElement(),
typeDefinition);
if (typeDefinitionName == null) {
continue;
}
final Set<EObject> resultLocus = new HashSet<EObject>();
resultLocus.add(locusFeature);
statusList.add(ConstraintStatus.createStatus(ctx, namedComponent, resultLocus, MessageFormat.format(
Messages.UnresolvedXsdContentsValidation_type_reference_X_Y_is_unresolved_validation_msg, typeDefinition
.getTargetNamespace(), typeDefinitionName), IStatus.ERROR));
}
}
private XSDTypeDefinition getTypeDefinition(final XSDNamedComponent namedComponent) {
if (namedComponent instanceof XSDAttributeDeclaration) {
return ((XSDAttributeDeclaration) namedComponent).getTypeDefinition();
} else if (namedComponent instanceof XSDElementDeclaration) {
return ((XSDElementDeclaration) namedComponent).getTypeDefinition();
}
return null;
}
private void validateAttributeReferences(final IValidationContext ctx,
final List<XSDNamedComponent> attributesForReferenceResolve, final List<IStatus> statusList) {
for (final XSDNamedComponent xsdAttributeDeclaration : attributesForReferenceResolve) {
final XSDAttributeDeclaration resolvedAttributeDeclaration = ((XSDAttributeDeclaration) xsdAttributeDeclaration)
.getResolvedAttributeDeclaration();
if (resolvedAttributeDeclaration.eContainer() == null) {
continue;
}
final Set<EObject> resultLocus = new HashSet<EObject>();
resultLocus.add(XSDPackage.Literals.XSD_ATTRIBUTE_DECLARATION__ATTRIBUTE_DECLARATION_REFERENCE);
statusList.add(ConstraintStatus.createStatus(ctx, xsdAttributeDeclaration, resultLocus, MessageFormat.format(
Messages.UnresolvedXsdContentsValidation_attributes_reference_X_Y_is_unresolved_msg,
resolvedAttributeDeclaration.getTargetNamespace(), resolvedAttributeDeclaration.getName()), IStatus.ERROR));
}
}
private void validateComplexTypeDefinitions(final IValidationContext ctx,
final List<XSDNamedComponent> complexTypesForResolve, final List<IStatus> statusList, final String derivationMethod) {
for (final XSDNamedComponent xsdComplexTypeDefinition : complexTypesForResolve) {
final XSDTypeDefinition baseTypeDefinition = ((XSDComplexTypeDefinition) xsdComplexTypeDefinition)
.getBaseTypeDefinition();
final String typeDefinitionName = XsdComplexTypeDefinitionExtensionResolver.getResolveComponentLocalName(
((XSDComplexTypeDefinition) xsdComplexTypeDefinition), derivationMethod);
if (typeDefinitionName == null) {
continue;
}
final Set<EObject> resultLocus = new HashSet<EObject>();
resultLocus.add(XSDPackage.Literals.XSD_COMPLEX_TYPE_DEFINITION__BASE_TYPE_DEFINITION);
statusList.add(ConstraintStatus.createStatus(ctx, xsdComplexTypeDefinition, resultLocus, MessageFormat.format(
Messages.UnresolvedXsdContentsValidation_type_reference_X_Y_is_unresolved_validation_msg, baseTypeDefinition
.getTargetNamespace(), typeDefinitionName), IStatus.ERROR));
}
}
@Override
protected boolean shouldExecute(final IValidationContext ctx) {
if (isBatchValidation(ctx)) {
return false;
}
return ctx.getTarget() instanceof XSDConcreteComponent;
}
}