/** * <copyright> * Copyright (c) 2010-2014 Henshin developers. 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 * </copyright> */ package org.eclipse.emf.henshin.interpreter.matching.constraints; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature.Setting; import org.eclipse.emf.henshin.interpreter.EGraph; /** * This constraint checks whether the value of an EReference contains objects * from the target domain. * * @authot Enrico Biermann, Christian Krause */ public class DanglingConstraint implements Constraint { // Outgoing edge count: private final Map<EReference, Integer> outgoingEdgeCount; // Incoming edge count: private final Map<EReference, Integer> incomingEdgeCount; /** * Default constructor. * @param outgoingEdgeCount Outgoing edge count. * @param incomingEdgeCount Incoming edge count. */ public DanglingConstraint( Map<EReference, Integer> outgoingEdgeCount, Map<EReference, Integer> incomingEdgeCount) { this.outgoingEdgeCount = outgoingEdgeCount; this.incomingEdgeCount = incomingEdgeCount; } /* * */ @SuppressWarnings("unchecked") public boolean check(EObject sourceValue, EGraph graph) { // Compute the actual number of incoming edges: Collection<Setting> settings = graph.getCrossReferenceAdapter().getInverseReferences(sourceValue); Map<EReference, Integer> actualIncomingEdges = createMapFromSettings(settings); Integer expectedCount; if (incomingEdgeCount != null) { for (EReference ref: actualIncomingEdges.keySet()) { if (incomingEdgeCount.containsKey(ref)) { expectedCount = incomingEdgeCount.get(ref); } else { expectedCount = 0; } if (actualIncomingEdges.get(ref) > expectedCount) { return false; } } } else { if (!actualIncomingEdges.isEmpty()) { return false; } } // Outgoing references for (EReference type : sourceValue.eClass().getEReferences()) { if (!type.isDerived()) { if (outgoingEdgeCount != null && outgoingEdgeCount.containsKey(type)) { expectedCount = outgoingEdgeCount.get(type); } else { expectedCount = 0; } if (type.isMany()) { List<Object> outgoingEdges = (List<Object>) sourceValue.eGet(type); outgoingEdges.retainAll(graph); if (expectedCount!=null) { if (expectedCount!=outgoingEdges.size()) { return false; } } } else { if (sourceValue.eGet(type)!=null && expectedCount!=1 && graph.contains(sourceValue.eGet(type))) { return false; } } } } // Ok. return true; } /* * Count edges. */ private Map<EReference, Integer> createMapFromSettings(Collection<Setting> settings) { Map<EReference, Integer> result = new HashMap<EReference, Integer>(); for (Setting setting: settings) { Integer count = result.get(setting.getEStructuralFeature()); if (count == null) { count = 1; result.put((EReference) setting.getEStructuralFeature(), count); } else { count++; } } return result; } }