/*******************************************************************************
* Copyright (c) 2011, 2012 Red Hat, Inc.
* All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.bpmn2.modeler.core.validation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.bpmn2.modeler.core.Activator;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EValidator;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.ui.util.EditUIMarkerHelper;
import org.eclipse.emf.validation.marker.MarkerUtil;
import org.eclipse.emf.validation.model.ConstraintStatus;
import org.eclipse.emf.validation.model.IModelConstraint;
import org.eclipse.emf.validation.service.ConstraintFactory;
import org.eclipse.emf.validation.service.ConstraintRegistry;
import org.eclipse.emf.validation.service.IConstraintDescriptor;
import org.eclipse.graphiti.ui.editor.DiagramEditor;
public class BPMN2ValidationStatusLoader {
DiagramEditor editor;
public BPMN2ValidationStatusLoader(DiagramEditor editor) {
this.editor = editor;
}
public Set<EObject> load(List<IMarker> markers) {
if (markers == null) {
return Collections.emptySet();
}
Set<EObject> touched = new LinkedHashSet<EObject>();
for (IMarker marker : markers) {
for (EObject markedObject : getAllObjects(marker)) {
if (markedObject == null) {
continue;
}
ValidationStatusAdapter statusAdapter = (ValidationStatusAdapter) EcoreUtil.getRegisteredAdapter(
markedObject, ValidationStatusAdapter.class);
// add the adapter factory for tracking validation errors
if (statusAdapter==null) {
ResourceSet resourceSet = editor.getEditingDomain().getResourceSet();
resourceSet.getAdapterFactories().add(new ValidationStatusAdapterFactory());
statusAdapter = (ValidationStatusAdapter) EcoreUtil.getRegisteredAdapter(
markedObject, ValidationStatusAdapter.class);
}
// convert the problem marker to an IStatus suitable for the validation status adapter
IStatus status = convertMarker(marker, markedObject);
// also add an adapter to each affected EObject in the result locus
if (status instanceof ConstraintStatus) {
ConstraintStatus cs = (ConstraintStatus) status;
for (EObject result : cs.getResultLocus()) {
// CAUTION: the result locus WILL contain references to object
// features (EStructuralFeatures) that identify the feature in
// error for the Property Sheets. We don't want to add a validation
// status adapter to these EObjects.
if (result!=markedObject) {
EPackage pkg = result.eClass().getEPackage();
if (pkg != EcorePackage.eINSTANCE) {
ValidationStatusAdapter sa = (ValidationStatusAdapter) EcoreUtil.getRegisteredAdapter(
result, ValidationStatusAdapter.class);
sa.addValidationStatus(status);
touched.add(result);
}
}
}
}
statusAdapter.addValidationStatus(status);
touched.add(markedObject);
}
}
return touched;
}
private List<EObject> getAllObjects(IMarker marker) {
List<EObject> result = new ArrayList<EObject>();
result.add(getTargetObject(marker));
result.addAll(getRelatedObjects(marker));
return result;
}
private List<EObject> getRelatedObjects(IMarker marker) {
List<EObject> result = new ArrayList<EObject>();
String targetUri = marker.getAttribute(EValidator.URI_ATTRIBUTE, null);
String uriString = marker.getAttribute(EValidator.RELATED_URIS_ATTRIBUTE,null);
if (uriString!=null) {
String[] uris = uriString.split(" "); //$NON-NLS-1$
for (String s : uris) {
if (s.equals(targetUri))
continue;
URI uri = URI.createURI(s);
EObject o = editor.getEditingDomain().getResourceSet().getEObject(uri, false);
if (!(o instanceof EStructuralFeature))
result.add(o);
}
}
return result;
}
private EObject getTargetObject(IMarker marker) {
final String uriString = marker.getAttribute(EValidator.URI_ATTRIBUTE, null);
final URI uri = uriString == null ? null : URI.createURI(uriString);
if (uri == null) {
return null;
}
return editor.getEditingDomain().getResourceSet().getEObject(uri, false);
}
@SuppressWarnings("unchecked")
private IStatus convertMarker(IMarker marker, EObject target) {
final String message = marker.getAttribute(IMarker.MESSAGE, ""); //$NON-NLS-1$
final String constraintId = marker.getAttribute(MarkerUtil.RULE_ATTRIBUTE, null);
final IConstraintDescriptor icd = constraintId == null ? null : ConstraintRegistry.getInstance().getDescriptor(
constraintId);
final IModelConstraint imc = icd == null ? null : ConstraintFactory.getInstance().newConstraint(icd);
if (imc == null) {
final int severity;
switch (marker.getAttribute(IMarker.SEVERITY, -1)) {
case IMarker.SEVERITY_INFO:
severity = IStatus.INFO;
break;
case IMarker.SEVERITY_WARNING:
severity = IStatus.WARNING;
break;
case IMarker.SEVERITY_ERROR:
severity = IStatus.ERROR;
break;
default:
severity = IStatus.OK;
}
return new Status(severity, Activator.PLUGIN_ID, message);
}
List<?> locus = new EditUIMarkerHelper().getTargetObjects(editor.getEditingDomain(), marker);
for (Iterator<?> it = locus.iterator(); it.hasNext();) {
if (!(it.next() instanceof EObject)) {
it.remove();
}
}
return new ConstraintStatus(imc, target, message, locus == null ? null : new LinkedHashSet<EObject>(
(List<? extends EObject>) locus));
}
}