Skip to content

Commit

Permalink
Bug 459804 - ModelMutator should be configurable to not generate cycles
Browse files Browse the repository at this point in the history
small refactoring & javadoc
  • Loading branch information
edgarmueller committed Feb 12, 2015
1 parent 76431c1 commit c5c8e61
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
package org.eclipse.emf.emfstore.modelmutator;
/*******************************************************************************
* Copyright (c) 2015 EclipseSource Muenchen GmbH and others.
*
* 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:
* Edgar Mueller - initial API and implementation
******************************************************************************/
package org.eclipse.emf.emfstore.internal.modelmutator.mutation;

import java.util.List;

Expand All @@ -12,8 +23,31 @@
import org.jgrapht.graph.DefaultDirectedGraph;
import org.jgrapht.graph.DefaultEdge;

public class Loop {
/**
* Utility class for detecting any cycles within an {@link EObject}.
*
* @author emueller
*
*/
public final class EMFCycleDetector {

private EMFCycleDetector() {
// private ctor
}

/**
* Checks whether the given {@link EObject} would contain a
* cycle if a edge, that is, a reference (containment or non-containment),
* from <code>source</code> to <code>target</code> is inserted.
*
* @param root
* the root {@link EObject} forming the graph
* @param source
* the source of the edge
* @param target
* the target of the edge
* @return {@code true} if {@code root} would contain a cycle, {@code false} otherwise
*/
public static boolean wouldBeCycle(EObject root, EObject source, EObject target) {
final DirectedGraph<EObject, DefaultEdge> graph = makeGraph(root);
assertVertexIsKnown(graph, source);
Expand All @@ -22,23 +56,22 @@ public static boolean wouldBeCycle(EObject root, EObject source, EObject target)
return detectCycle(graph);
}

/**
* Detects cycles within the {@link EObject} graph of the given object.
*
* @param eObject
* the {@link EObject} which should be checked for cycles
* @return {@code true} if the given object contains a cycle, {@code false} otherwise
*/
public static boolean detect(EObject eObject) {
final DirectedGraph<EObject, DefaultEdge> graph = makeGraph(eObject);
return detectCycle(graph);
}

/**
* @param graph
* @return
*/
private static boolean detectCycle(final DirectedGraph<EObject, DefaultEdge> graph) {
return new CycleDetector<EObject, DefaultEdge>(graph).detectCycles();
}

/**
* @param eObject
* @return
*/
private static DirectedGraph<EObject, DefaultEdge> makeGraph(EObject eObject) {
final DirectedGraph<EObject, DefaultEdge> graph =
new DefaultDirectedGraph<EObject, DefaultEdge>(DefaultEdge.class);
Expand Down Expand Up @@ -71,10 +104,6 @@ private static DirectedGraph<EObject, DefaultEdge> makeGraph(EObject eObject) {
return graph;
}

/**
* @param graph
* @param target
*/
private static void assertVertexIsKnown(final DirectedGraph<EObject, DefaultEdge> graph, final Object target) {
if (!graph.vertexSet().contains(target)) {
graph.addVertex((EObject) target);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import org.eclipse.emf.emfstore.internal.modelmutator.intern.attribute.AttributeSetterELong;
import org.eclipse.emf.emfstore.internal.modelmutator.intern.attribute.AttributeSetterEShort;
import org.eclipse.emf.emfstore.internal.modelmutator.intern.attribute.AttributeSetterEString;
import org.eclipse.emf.emfstore.internal.modelmutator.mutation.EMFCycleDetector;
import org.eclipse.emf.emfstore.internal.modelmutator.mutation.MutationPredicates;

import com.google.common.base.Predicate;
Expand Down Expand Up @@ -781,11 +782,6 @@ private List<EStructuralFeature> getAvailableFeatureKeys(EClass eClass) {
return eStructuralFeatures;
}

class Pair {
public EStructuralFeature feature;
public EObject value;
}

/**
* @param random
* @param uninitializedFeatureMapEntries
Expand Down Expand Up @@ -883,7 +879,7 @@ private EObject selectUnusedEObject(final Random random, EClass desiredClass,
}
}

public EObject createOfType(EClass eClass) {
private EObject createOfType(EClass eClass) {
final EObject eObjectToAdd = EcoreUtil.create(eClass);
setEObjectAttributes(eObjectToAdd);
return eObjectToAdd;
Expand Down Expand Up @@ -1101,7 +1097,7 @@ public void setReference(EObject eObject, EClass referenceClass, EReference refe
// if the reference is ordered, do not use an index
final Integer newIndex = reference.isOrdered() ? null : random.nextInt(size);
final EObject target = possibleReferenceObjects.get(index);
if (!Loop.wouldBeCycle(config.getRootEObject(), eObject, target)) {
if (!EMFCycleDetector.wouldBeCycle(config.getRootEObject(), eObject, target)) {
setPerCommand(eObject, reference, target, newIndex);
} else {
// TODO
Expand All @@ -1113,7 +1109,7 @@ public void setReference(EObject eObject, EClass referenceClass, EReference refe
}
} else {
final EObject target = possibleReferenceObjects.get(index);
if (!Loop.wouldBeCycle(config.getRootEObject(), eObject, target)) {
if (!EMFCycleDetector.wouldBeCycle(config.getRootEObject(), eObject, target)) {
addPerCommand(eObject, reference, target, random.nextBoolean()
&& size > 0 ? random.nextInt(size) : null);
} else {
Expand All @@ -1128,7 +1124,7 @@ public void setReference(EObject eObject, EClass referenceClass, EReference refe
}
} else if (random.nextBoolean() || reference.isRequired()) {
final EObject target = possibleReferenceObjects.get(index);
if (!Loop.wouldBeCycle(config.getRootEObject(), eObject, target)) {
if (!EMFCycleDetector.wouldBeCycle(config.getRootEObject(), eObject, target)) {
setPerCommand(eObject, reference, target);
} else {
// TODO
Expand Down

0 comments on commit c5c8e61

Please sign in to comment.