Refactored and documented Helper classes

This commit introduces some changes in the implementation of EMFHelper which simplify
some of its methods. It also contains improved documentation for EMFHelper methods as
well as the ArtifactHelper class to clarify the contracts of the methods therein.

Change-Id: I34457c96f7672fa3f23122498965148d31a16543
diff --git a/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/helpers/ArtifactHelper.java b/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/helpers/ArtifactHelper.java
index d68392b..303e322 100644
--- a/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/helpers/ArtifactHelper.java
+++ b/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/helpers/ArtifactHelper.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2016, 2019 Chalmers | University of Gothenburg, rt-labs and others.
+ * Copyright (c) 2016, 2021 Chalmers | University of Gothenburg, rt-labs and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v2.0
  * which accompanies this distribution, and is available at
@@ -25,6 +25,9 @@
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.util.EcoreUtil;
 
+/**
+ * Provides support methods for working with artifacts and wrappers.
+ */
 public class ArtifactHelper {
 
 	private static final String QUOTE_CHARACTERS = "[\"\']";
@@ -50,17 +53,23 @@
 	}
 
 	/**
-	 * @param artifactModel
+	 * Constructs a new {@code ArtifactHelper} for the given artifact model.
+	 * 
+	 * @param artifactModel the model containing the artifact this helper should
+	 *                      access
 	 */
 	public ArtifactHelper(EObject artifactModel) {
 		this.artifactModel = artifactModel;
 	}
 
 	/**
-	 * Creates wrappers for artifacts
+	 * Creates wrappers for the given artifacts. For this purpose, this method
+	 * identifies the handler for each artifact and retrieves a wrapper from the
+	 * handler.
 	 *
-	 * @param artifacts
-	 * @return List of wrappers
+	 * @param artifacts the artifacts that should be wrapped
+	 * @return a list of wrappers for the given artifacts
+	 * @see IArtifactHandler#createWrapper(Object, EObject)
 	 */
 	public List<EObject> createWrappers(List<?> artifacts) {
 		return artifacts.stream()
@@ -75,7 +84,7 @@
 	 * returned by {@link #getHandler(Object)}.
 	 *
 	 * @param vagueArtifact the object that should be wrapped
-	 * @return the wrapped artifact or null if no handler exists
+	 * @return the wrapped artifact or {@code null} if no handler exists
 	 */
 	public EObject createWrapper(Object vagueArtifact) {
 		Optional<EObject> wrapped = getHandler(vagueArtifact)
@@ -87,7 +96,8 @@
 
 	/**
 	 * Unwraps an artifact wrapper to get its original object. If the original
-	 * object is <code>null</code>, the wrapper is returned as it is.
+	 * object is <code>null</code>, the wrapper is returned as it is. If the
+	 * provided object is not a wrapper, it is also returned as is.
 	 * 
 	 * @param wrapper to be unwrapped
 	 * @return the original artifact
diff --git a/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/helpers/EMFHelper.java b/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/helpers/EMFHelper.java
index 1792523..a9fb19c 100644
--- a/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/helpers/EMFHelper.java
+++ b/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/helpers/EMFHelper.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2016, 2019 Chalmers | University of Gothenburg, rt-labs and others.
+ * Copyright (c) 2016, 2021 Chalmers | University of Gothenburg, rt-labs and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v2.0
  * which accompanies this distribution, and is available at
@@ -57,12 +57,9 @@
 		List<EAttribute> attributes = eObject.eClass().getEAllAttributes();
 		StringBuilder identifier = new StringBuilder();
 
-		success = tryGetSingleAttribute(eObject, attributes, identifier);
+		success = tryGetNameAttribute(eObject, identifier);
 
-		if (!success) {
-			success = tryGetNameAttribute(eObject, attributes, identifier);
-		}
-
+		// We didn't find a name. Try finding something else that we can use.
 		if (!success) {
 			success = tryGetAnyAttribute(eObject, attributes, identifier);
 		}
@@ -77,75 +74,90 @@
 	}
 
 	/**
-	 * @param name Use an empty StringBuilder as input. If this function returns
-	 *             true, this parameter has been filled, if it returns false,
-	 *             nothing happened.
-	 * @return Indicates the success of this function and if the last parameter
-	 *         contains output.
+	 * Tries to retrieve a {@code String} representation of the provided
+	 * {@code EAttribute} for the provided {@code EObject}. If the attribute is
+	 * {@code null}, it is not a valid attribute of the given {@code EObject} or the
+	 * value of the attribute is {@code} null, this method will return {@code false}
+	 * and the provided {@code StringBuilder} will not be altered.
+	 * 
+	 * @param builder {@code StringBuilder} to construct the String representation
+	 *                of the provided {@code EAttribute}. If this method returns
+	 *                {@code true}, this parameter has been changed, if it returns
+	 *                {@code false}, the {@code StringBuilder} is unaltered.
+	 * @return indicates the success of this function and if the
+	 *         {@code StringBuilder} contains output.
 	 */
-	public static boolean tryGetSingleAttribute(final EObject eObject, final List<EAttribute> attributes,
-			final StringBuilder name) {
+	public static boolean tryGetAttribute(final EObject eObject, final EAttribute attribute, final StringBuilder name) {
 		boolean success = false;
-		if (attributes.size() == 1) {
-			Object obj = eObject.eGet(attributes.get(0));
-			if (obj != null) {
-				name.append(obj.toString());
-				success = true;
-			}
-		}
-		return success;
-	}
-
-	/**
-	 * @param name Use an empty StringBuilder as input. If this function returns
-	 *             true, this parameter has been filled, if it returns false,
-	 *             nothing happened.
-	 * @return Indicates the success of this function and if the last parameter
-	 *         contains output.
-	 */
-	public static boolean tryGetNameAttribute(final EObject eObject, final List<EAttribute> attributes,
-			final StringBuilder name) {
-		boolean success = false;
-		for (EAttribute feature : attributes) {
-			if (feature.getName().equals("name")) {
-				Object obj = eObject.eGet(feature);
+		if (attribute != null) {
+			try {
+				Object obj = eObject.eGet(attribute);
 				if (obj != null) {
 					name.append(obj.toString());
 					success = true;
-					break;
 				}
+			} catch (IllegalArgumentException ex) {
+				// Deliberately do nothing.
+				// This can happen if the provided attribute is not an attribute of the eObject.
+				// In this case, we just want the method to return false, which it does if we
+				// just hold our feet still.
 			}
 		}
 		return success;
 	}
 
 	/**
-	 * @param name Use an empty StringBuilder as input. If this function returns
-	 *             true, this parameter has been filled, if it returns false,
-	 *             nothing happened.
-	 * @return Indicates the success of this function and if the last parameter
-	 *         contains output.
+	 * Tries to retrieve a String representation of the attribute "name" from the
+	 * provided {@code EObject}.
+	 * 
+	 * @param builder {@code StringBuilder} to construct the String representation
+	 *                of the {@code EObject}'s "name" attribute. If this function
+	 *                returns {@code true}, this parameter has been filled, if it
+	 *                returns {@code false}, the {@code StringBuilder} is unaltered.
+	 * @return indicates the success of this function and if the
+	 *         {@code StringBuilder} contains output.
+	 * @see #tryGetAttribute(EObject, EAttribute, StringBuilder)
+	 */
+	public static boolean tryGetNameAttribute(final EObject eObject, final StringBuilder builder) {
+		boolean success = false;
+		for (EAttribute attribute : eObject.eClass().getEAllAttributes()) {
+			if (attribute.getName().equals("name")) {
+				success = tryGetAttribute(eObject, attribute, builder);
+			}
+		}
+		return success;
+	}
+
+	/**
+	 * Attempts to retrieve a {@code String} representation of any of the given
+	 * attributes. For that purpose, it iterates over all attributes until it finds
+	 * one which is not null and non-empty. It then adds the String representation
+	 * of that attribute's value to the provided {@code StringBuilder} and returns
+	 * {@code true}.
+	 * 
+	 * @param builder {@code StringBuilder} to construct the String representation
+	 *                of the first non-null, non-empty attribute. If this function
+	 *                returns {@code true}, this parameter has been filled, if it
+	 *                returns {@code false}, the {@code StringBuilder} is unaltered.
+	 * @return indicates the success of this function and if the
+	 *         {@code StringBuilder} contains output.
 	 */
 	public static boolean tryGetAnyAttribute(final EObject eObject, final List<EAttribute> attributes,
 			final StringBuilder name) {
 		boolean success = false;
-		String nonStringName = null;
-		String stringName = null;
+		String stringName = "";
 		for (EAttribute feature : attributes) {
 			Object obj = eObject.eGet(feature);
 			if (obj instanceof String) {
 				stringName = (String) obj;
-				break;
 			} else if (obj != null) {
-				nonStringName = obj.toString();
+				stringName = obj.toString();
 			}
-		}
-		if (stringName != null && !stringName.equals("null")) {
-			name.append(stringName);
-			success = true;
-		} else if (nonStringName != null && !nonStringName.equals("null")) {
-			name.append(nonStringName);
-			success = true;
+			if (stringName != null && !stringName.equals("null")) {
+				name.append(stringName);
+				success = true;
+				break;
+			}
 		}
 		return success;
 	}
@@ -177,16 +189,9 @@
 	 * @return String
 	 */
 	public static String getNameAttribute(final EObject eObject) {
-		String name = "";
-		for (EAttribute feature : eObject.eClass().getEAllAttributes()) {
-			if (feature.getName().equals("name")) {
-				Object obj = eObject.eGet(feature);
-				if (obj != null) {
-					name = obj.toString();
-				}
-			}
-		}
-		return name;
+		StringBuilder name = new StringBuilder();
+		tryGetNameAttribute(eObject, name);
+		return name.toString();
 	}
 
 	/**