package gov.nasa.jpl.mbee.mdk.emf;
import com.nomagic.uml2.ext.jmi.helpers.StereotypesHelper;
import com.nomagic.uml2.ext.magicdraw.classes.mdkernel.Element;
import com.nomagic.uml2.ext.magicdraw.mdprofiles.Stereotype;
import gov.nasa.jpl.mbee.mdk.api.incubating.convert.Converters;
import gov.nasa.jpl.mbee.mdk.util.*;
import gov.nasa.jpl.mbee.mdk.util.Pair;
import junit.framework.Assert;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
public final class EmfUtils {
public static String toString(Object o) {
if (o == null) {
return "null";
}
if (o instanceof Collection) {
Collection<?> c = (Collection<?>) o;
int count = 0;
while (c.size() == 1 && c != c.iterator().next() && count++ < 5) {
o = c.iterator().next();
if (o instanceof Collection) {
c = (Collection<?>) o;
}
}
if (c == o && c.size() != 1) {
StringBuffer sb = new StringBuffer();
sb.append("(");
boolean first = true;
for (Object oo : c) {
if (first) {
first = false;
}
else {
sb.append(", ");
}
sb.append(toString(oo));
}
sb.append(")");
return sb.toString();
}
}
else if (o.getClass().isArray()) {
Object[] arr = (Object[]) o;
if (arr.length == 1) {
return toString(arr[0]);
}
// TODO -- potential infinite loop -- use Utils2.seen()
return toString(Arrays.asList(arr));
}
String result = null;
String name = getName(o);
if (Utils2.isNullOrEmpty(name)) {
name = "";
}
else {
name = name + ":";
}
if (o instanceof Element) {
Element e = (Element) o;
String repText = e.get_representationText();
if (Utils2.isNullOrEmpty(repText)) {
repText = "";
}
else {
repText = ":" + repText;
}
result = name + // e.getHumanType() + ":" +
(Debug.isOn() ? Converters.getElementToIdConverter().apply(e) : "") + repText;
result = result.replaceFirst("::", ":");
result = result.trim().replaceAll("^:", "");
result = result.trim().replaceAll(":$", "");
return result;
}
if (Utils2.isNullOrEmpty(name)) {
result = o.toString();
}
else {
result = name + getTypeNames(o);
}
result = result.trim().replaceAll("^:", "");
result = result.trim().replaceAll(":$", "");
return result;
}
/**
* @param specifier
* @return
*/
public static List<String> getPossibleFieldNames(String specifier) {
List<String> possibleFieldNames = new ArrayList<String>();
// get field(s) with matching name
possibleFieldNames.add(specifier);
possibleFieldNames.add(specifier.toUpperCase(Locale.US));
possibleFieldNames.add(specifier.toLowerCase(Locale.US));
String capitalizedSpec = Utils2.capitalize(specifier);
if (Character.isLowerCase(specifier.charAt(0))) {
possibleFieldNames.add(capitalizedSpec);
}
return possibleFieldNames;
}
/**
* @param specifier
* @return
*/
public static List<String> getPossibleMethodNames(String specifier) {
return getPossibleMethodNames(specifier, "e", "eGet", "get", "get_");
}
/**
* @param specifier
* @param methodPrefixes
* @return methods with names that match the specifier or the specifier with
* one of the method prefixes
*/
public static List<String> getPossibleMethodNames(String specifier, String... methodPrefixes) {
// get methods with matching names
List<String> possibleMethodNames = getPossibleFieldNames(specifier);
String capitalizedSpec = Utils2.capitalize(specifier);
for (String prefix : methodPrefixes) {
possibleMethodNames.add(prefix + capitalizedSpec);
}
return possibleMethodNames;
}
/**
* Determines the validity of a return value packaged with a {@link Boolean}
* in a {@link Pair}.
* <p>
* <p>
* A method may return a success/fail {@link Boolean} with another return
* value in a pair. For example, a getValue() method may want to return null
* sometimes as a valid value and at other times as an invalid value.
* <p>
* <p>
* The {@link Boolean} may be null, which this method assumes means that
* success is "unknown." When unknown, this method gives the benefit of the
* doubt for non-null return values, so true is returned for Pair(null,
* nonNullT), and false for Pair(null,null), assuming that an unsuccessful
* call always has a null return value.
*
* @param p a return value from another function paired with a success
* flag, Pair(Boolean success, T returnValue).
* @return true if the success flag is true or null with a non-null return
* value.
*/
public static <T> boolean trueOrNotNull(Pair<Boolean, T> p) {
return (p.getKey() == null && p.getValue() != null) || (p.getKey() != null && p.getKey());
}
/**
* Get the values of the object's fields that have one the specified names
* (or, if not strict, some close variation). Only return values that are
* instances of the specified {@link Class}. If cls is null, return all
* values for matching fields.
*
* @param o
* @param cls
* @param propagate
* @param justFirst
* @param specifiers
* @return field members of o that have one of the specified names or are
* instances of cls
*/
public static <T> List<T> getMethodResults(Object o, Class<T> cls, boolean propagate,
boolean strictMatch, boolean justFirst, String... specifiers) {
LinkedHashSet<T> results = new LinkedHashSet<T>();
if (o == null || specifiers == null) {
return Collections.emptyList();
}
for (String specifier : specifiers) {
List<String> possibleMethodNames = (strictMatch ? Utils2.newList(specifier)
: getPossibleMethodNames(specifier));
for (String name : possibleMethodNames) {
Method[] methods = ClassUtils.getMethodsForName(o.getClass(), name);
if (methods != null) {
for (Method method : methods) {
// TODO -- pass in potential arguments? can they be
// deduced?
Pair<Boolean, Object> pr = ClassUtils.runMethod(true, o, method);
if (trueOrNotNull(pr)) {
Pair<Boolean, T> pc = ClassUtils.coerce(pr.getValue(), cls);
if (trueOrNotNull(pc)) {
results.add(pc.getValue());
if (justFirst) {
return Utils2.asList(results);
}
}
}
}
}
}
}
return Utils2.asList(results);
}
/**
* Get methods whose names are variations of those specified and return the
* results of their invocations. Only return values that are instances of
* the specified {@link Class}. If cls is null, return all values for
* matching members.
*
* @param o
* @param cls
* @param propagate
* @param justFirst
* @param specifiers
* @return member values of o that have one of the specified names or are
* instances of cls
*/
public static <T> List<T> getFieldValues(Object o, Class<T> cls, boolean propagate, boolean strictMatch,
boolean justFirst, String... specifiers) {
LinkedHashSet<T> results = new LinkedHashSet<T>();
if (o == null || specifiers == null) {
return Collections.emptyList();
}
for (String specifier : specifiers) {
List<String> possibleFieldNames = (strictMatch ? Utils2.newList(specifier)
: getPossibleFieldNames(specifier));
for (String name : possibleFieldNames) {
if (ClassUtils.getField(o, name) != null) {
Object r = ClassUtils.getField(o, name);
Pair<Boolean, T> p = // Expression.
ClassUtils.coerce(r, cls);
if (trueOrNotNull(p)) {
results.add(p.getValue());
if (justFirst) {
return Utils2.asList(results);
}
}
}
}
}
return Utils2.asList(results);
}
@SuppressWarnings("unchecked")
public static <T extends Object> List<T> getFieldValues(Object o, boolean includeStatic) {
List<T> results = new ArrayList<T>();
for (Field f : o.getClass().getFields()) {
if (!includeStatic && ClassUtils.isStatic(f)) {
continue;
}
f.setAccessible(true);
T t = null;
try {
t = (T) f.get(o);
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
results.add(t);
}
return results;
}
/**
* Get the value of the object's field with the specified name (or some
* close variation). Or, if the field does not exist, find a method whose
* name is a variation of the one specified and return the result of its
* invocation.
*
* @param o
* @param specifier
* @param propagate
* @return
*/
public static Object getMemberValue(Object o, String specifier, boolean propagate, boolean strictMatch) {
List<Object> members = getMemberValues(o, Object.class, propagate, strictMatch, true, specifier);
if (Utils2.isNullOrEmpty(members)) {
return null;
}
return members.get(0);
}
/**
* Get the values of the object's fields that have one the specified names
* (or some close variation). Then get methods whose names are variations of
* those specified and return the results of their invocations. Only return
* values that are instances of the specified {@link Class}. If cls is null,
* return all values for matching members.
*
* @param o
* @param cls
* @param propagate
* @param justFirst
* @param specifiers
* @param strictMatch
* @return member values of o that have one of the specified names or are
* instances of cls
*/
public static <T> List<T> getMemberValues(Object o, Class<T> cls, boolean propagate, boolean strictMatch,
boolean justFirst, String... specifiers) {
if (o == null || specifiers == null) {
return Collections.emptyList();
}
LinkedHashSet<T> results = new LinkedHashSet<T>();
results.addAll(getFieldValues(o, cls, propagate, true, justFirst, specifiers));
if (justFirst && !results.isEmpty()) {
return Utils2.asList(results);
}
results.addAll(getFieldValues(o, cls, propagate, true, justFirst, specifiers));
if (justFirst && !results.isEmpty()) {
return Utils2.asList(results);
}
if (!strictMatch) {
results.addAll(getMethodResults(o, cls, propagate, false, justFirst, specifiers));
if (justFirst && !results.isEmpty()) {
return Utils2.asList(results);
}
results.addAll(getMethodResults(o, cls, propagate, false, justFirst, specifiers));
}
return Utils2.asList(results);
}
public static Collection<Class<?>> getTypes(Object o) {
if (o == null) {
return null;
}
EObject eo = (EObject) (o instanceof EObject ? o : null);
Collection<Class<?>> results = new LinkedHashSet<Class<?>>();
if (eo != null) {
results.addAll(getTypes(eo, true, true, true, true, null));
}
// results.add( o.getClass() );
results.addAll(ClassUtils.getAllClasses(o));
return results;
}
public static Class<?> getType(Object o) {
if (o == null) {
return null;
}
EObject eo = (EObject) (o instanceof EObject ? o : null);
Class<?> c = (eo != null ? getType(eo) : o.getClass());
return c;
}
public static String getTypeName(Object o) {
if (o == null) {
return null;
}
Class<?> c = getType(o);
if (c == null) {
return null;
}
return c.getSimpleName();
}
public static Collection<String> getTypeNames(Object o) {
Collection<Class<?>> types = getTypes(o);
if (types == null) {
return null;
}
Collection<String> results = new TreeSet<String>();
for (Class<?> t : types) {
results.add(t.getSimpleName());
}
return results;
}
public static String getName(Object o) {
String name = null;
// for the fancy EObject
EObject eo = (EObject) (o instanceof EObject ? o : null);
if (eo != null) {
if (o instanceof EClassifier) {
name = ((EClassifier) o).getInstanceClassName();
}
if (Utils2.isNullOrEmpty(name)) {
EStructuralFeature nameFeature = eo.eClass().getEStructuralFeature("name");
if (nameFeature != null) {
name = (String) eo.eGet(nameFeature);
}
}
if (Utils2.isNullOrEmpty(name)) {
if (eo instanceof Element) {
if (eo instanceof ENamedElement) {
name = ((ENamedElement) eo).getName();
}
else {
name = ((Element) eo).getHumanName();
}
}
}
}
if (Utils2.isNullOrEmpty(name)) {
// for the vanilla object
Object n = getMemberValue(o, "name", true, false);
if (n != null) {
name = n.toString();
}
}
return name;
}
public static void getEObjectsOfType(EObject o, Class<?> type, Set<EObject> set) {
assert set != null;
if (type.isAssignableFrom(o.getClass())) {
if (set.contains(o)) {
return;
}
else {
set.add(o);
}
}
Iterator<EObject> iter = o.eContents().iterator();
while (iter.hasNext()) {
EObject subO = iter.next();
getEObjectsOfType(subO, type, set);
}
}
public static Set<EObject> getEObjectsOfType(EObject o, Class<?> type) {
Set<EObject> set = new LinkedHashSet<EObject>();
getEObjectsOfType(o, type, set);
return set;
}
public static boolean contains(EObject outer, EObject inner) {
for (EObject o : getEObjectsOfType(outer, inner.getClass())) {
if (o == inner) {
return true;
}
}
return false;
}
/**
* @param eObj
* @param cls
* @param propagate whether to propagate value dependencies through Expressions.<br>
* TODO -- Expression-specific stuff like this should go back to
* Expression. A version of coerce() can be defined in ClassUtils
* without referencing Parameters and Expressions.
* @param strictMatch
* @param justFirst
* @return
*/
public static <TT> List<TT> getEValues(EObject eObj, Class<TT> cls, boolean propagate,
boolean strictMatch, boolean justFirst, boolean complainIfNotFound, SeenSet<Object> seen) {
// Check for bad input
if (eObj == null) {
if (complainIfNotFound) {
Debug.error(true, "Error! Passed null object to getValues().");
}
return Collections.emptyList();
}
// return if we've already tried this eObj to avoid infinite recursion
Pair<Boolean, Set<Object>> sp = Utils2.seen(eObj, true, (Set<Object>) seen);
if (sp.getKey()) {
return Collections.emptyList();
}
seen = (SeenSet<Object>) sp.getValue();
List<TT> results = new ArrayList<TT>();
// add "Value" to a list with its other words that may reference the
// value
List<String> list = Utils2.newList();
list.addAll(Arrays.asList(eWordsForValue));
boolean strictThisTime = true;
List<EStructuralFeature> seenFeatures = Utils2.newList();
Pair<Boolean, TT> p = null;
// At most two loop iterations. First loop is for strict matches. Second
// is
// for non-strict.
while (true) {
String[] sArr = new String[list.size()];
Utils2.toArrayOfType(list, sArr, String.class);
List<EStructuralFeature> features = findStructuralFeaturesMatching(eObj, strictThisTime, false,
sArr);
// remove strict matches that are duplicated in non-strict matches
features.removeAll(seenFeatures);
// collect seen features for next loop iteration
seenFeatures.addAll(features);
// get non-null results
Debug.outln("features=" + features);
for (EStructuralFeature f : features) {
if (f != null) {
Object res = eObj.eGet(f);
if (res != null) {
p = // Expression.
ClassUtils.coerce(res, cls);
if (trueOrNotNull(p)) {
results.add(p.getValue());
if (justFirst) {
return results;
}
}
}
}
}
// get results for contents
for (EObject eo : eObj.eContents()) {
// check if contained object's name matches
// boolean found = false;
String myName = getName(eo);
boolean noName = Utils2.isNullOrEmpty(myName);
if (!noName && list.contains(myName)) {
p = // Expression.
ClassUtils.coerce(eo, cls);
if (trueOrNotNull(p)) {
results.add(p.getValue());
if (justFirst) {
return results;
}
// found = true;
}
}
if (!noName && !strictThisTime) {
// non-strict name check
for (String name : list) {
if (myName.contains(name)) {
p = // Expression.
ClassUtils.coerce(eo, cls);
if (trueOrNotNull(p)) {
results.add(p.getValue());
if (justFirst) {
return results;
}
// found = true;
break;
}
}
}
}
// if ( !found ) {
// check if contained object has "values"
List<TT> resList = getValues(eo, cls, propagate, strictThisTime, justFirst, false, seen);
if (!Utils2.isNullOrEmpty(resList)) {
if (justFirst) {
return resList;
}
// Don't combine using Utils2.addAll(), which is unordered!
results.addAll(resList);
}
}
// }
if (strictMatch) {
break;
}
if (!strictThisTime) {
break;
}
strictThisTime = false;
// sizeOfLast = features.size(); // skip the ones we have already
// seen on the next loop
}
// If failed print the last Exception's stack trace.
if (complainIfNotFound && Utils2.isNullOrEmpty(results)) {
Debug.error(false, "Error! EmfUtils.getValues(" + getName(eObj) + ") found no value to return!");
}
return results;
}
/**
* Get a "value" corresponding to the {@link Object} that are instances of
* the input {@link Class} type.
*
* @param obj
* @param cls
* @param propagate
* @param strictMatch
* @param complainIfNotFound
* @return
*/
public static <TT> TT getValue(Object obj, Class<TT> cls, boolean propagate, boolean strictMatch,
boolean complainIfNotFound) {
List<TT> values = getValues(obj, cls, propagate, strictMatch, true, complainIfNotFound, null);
if (Utils2.isNullOrEmpty(values)) {
return null;
}
return values.get(0);
}
/**
* Get "values" corresponding to the {@link Object} that are instances of
* the input {@link Class} type.
*
* @param obj
* @param cls
* @param propagate
* @param strictMatch
* @param justFirst
* @param complainIfNotFound
* @return
*/
public static <TT> List<TT> getValues(Object obj, Class<TT> cls, boolean propagate, boolean strictMatch,
boolean justFirst, boolean complainIfNotFound, SeenSet<Object> seen) {
// Check for bad input
if (obj == null) {
if (complainIfNotFound) {
Debug.error(true, "Error! Passed null object to getValues().");
}
return Collections.emptyList();
}
// return if we've already tried this eObj to avoid infinite recursion
Pair<Boolean, SeenSet<Object>> sp = Utils2.seen(obj, true, seen);
if (sp.getKey()) {
return Collections.emptyList();
}
seen = sp.getValue();
List<TT> results = null;// new called by getMembers() call below. // new
// ArrayList< TT >();
Pair<Boolean, TT> p = null;
// Try for an exact match with a member field or function.
results = getMemberValues(obj, cls, propagate, true, justFirst, "value");
if (!Utils2.isNullOrEmpty(results) && justFirst) {
return results;
}
// Try getting value as an EObject.
EObject eObj = null;
if (obj instanceof EObject) {
eObj = (EObject) obj;
seen.remove(obj);
// Try getting strict matching values as an EObject. Will be less
// strict later.
List<TT> vList = EmfUtils.getEValues(eObj, cls, propagate, false, justFirst, false, seen);
if (justFirst && !vList.isEmpty()) {
return vList;
}
// Don't combine using Utils2.addAll(), which is unordered!
results.addAll(vList);
}
// Return the obj if it is already the *exact* right type.
if (cls != null && cls.equals(obj.getClass())) {
p = // Expression.
ClassUtils.coerce(obj, cls);
if (trueOrNotNull(p)) {
results.add(p.getValue());
if (justFirst) {
return results;
}
}
else {
Debug.error(true, "Error! Coercion of " + obj + " of type " + obj.getClass().getSimpleName()
+ " to " + cls.getSimpleName() + " unexpectedly failed!");
}
}
// Try finding members of other names that could mean "value."
String clsName = (cls == null ? "object" : cls.getSimpleName());
ArrayList<String> wordsForValueList = new ArrayList<String>();
String[] wordsForValue = new String[]{clsName + "Value", "literalValue", clsName};
wordsForValueList.addAll(Arrays.asList(wordsForValue));
wordsForValueList.addAll(Arrays.asList(EmfUtils.oWordsForValue));
wordsForValue = new String[wordsForValueList.size()];
Utils2.toArrayOfType(wordsForValueList, wordsForValue, String.class);
// Try for an exact match with a member field or function.
List<TT> resList = getMemberValues(obj, cls, propagate, strictMatch, justFirst,
wordsForValue);
if (justFirst && !resList.isEmpty()) {
return resList;
}
// Don't combine using Utils2.addAll(), which is unordered!
results.addAll(resList);
// Try to coerce the input obj to the correct type.
if (cls != null) {// && Utils2.isNullOrEmpty( results ) ) {
p = // Expression.
ClassUtils.coerce(obj, cls);
if (trueOrNotNull(p)) {
results.add(p.getValue());
if (justFirst) {
return results;
}
}
}
// if yet unsuccessful and cls == String.class return toString()
if (Utils2.isNullOrEmpty(results) && cls != null && cls.equals(String.class)) {
p = // Expression.
ClassUtils.coerce(obj.toString(), cls);
if (trueOrNotNull(p)) {
results.add(p.getValue());
if (justFirst) {
return results;
}
}
else {
// We should never get here.
String msg = "Error! Coercion of " + obj + " of type " + obj.getClass().getSimpleName()
+ " to " + cls.getSimpleName() + " unexpectedly failed!";
Assert.assertFalse(msg, true);
Debug.error(true, msg);
}
}
// If we aren't restricted by type and are yet unsuccessful, return the
// object itself.
if ((cls == null || cls.equals(Object.class)) && Utils2.isNullOrEmpty(results)) {
p = // Expression.
ClassUtils.coerce(obj, cls);
if (trueOrNotNull(p)) {
results.add(p.getValue());
if (justFirst) {
return results;
}
}
}
// If failed print the last Exception's stack trace.
if (complainIfNotFound && Utils2.isNullOrEmpty(results)) {
Debug.error(false, "Error! EmfUtils.getValues(" + getName(obj) + ") found no value to return!");
}
return results;
}
public static List<EStructuralFeature> findStructuralFeaturesMatching(EObject eObj, boolean strictMatch,
boolean justfirst, String... possibleNames) {
List<EStructuralFeature> features = new ArrayList<EStructuralFeature>();
ArrayList<String> list = new ArrayList<String>();
for (String s : possibleNames) {
if (!strictMatch) {
s = s.toLowerCase();
}
list.add(s);
}
TreeSet<String> names = new TreeSet<String>(list);
for (EStructuralFeature f : eObj.eClass().getEStructuralFeatures()) {
String fName = f.getName();
if (!strictMatch) {
fName = fName.toLowerCase();
}
if (names.contains(fName)) {
features.add(f);
if (justfirst) {
return features;
}
}
if (!strictMatch) {
for (String valueWord : names) {
if (fName.contains(valueWord)) {
features.add(f);
if (justfirst) {
return features;
}
}
}
}
}
return features;
}
public static Class<?> getType(EObject eObj) {
return getType(eObj, true);
}
public static Class<?> getType(EObject eObj, boolean strictMatch) {
List<Class<?>> list = getTypes(eObj, true, strictMatch, true, true, null);
if (!Utils2.isNullOrEmpty(list)) {
return list.get(0);
}
return null;
}
public static Class<?> asClass(Object obj, SeenSet<Object> seen) {
Class<?> cls = null;
if (obj instanceof EClassifier) {
cls = ((EClassifier) obj).getInstanceClass();
}
if (cls == null) {
cls = ClassUtils.evaluate(obj, Class.class);
}
if (cls == null) {
@SuppressWarnings("rawtypes")
List<Class> values = getValues(obj, Class.class, true, true, true, false, seen);
if (!Utils2.isNullOrEmpty(values)) {
cls = values.get(0);
}
}
return cls;
}
public static List<Class<?>> getTypes(EObject eObj, boolean propagate, boolean strictMatch,
boolean justFirst, boolean complainIfNotFound, SeenSet<Object> seen) {
List<Class<?>> results = new ArrayList<Class<?>>();
List<Object> typeObjects = getTypeObjects(eObj, propagate, strictMatch, justFirst,
complainIfNotFound, seen);
for (Object typeObj : typeObjects) {
if (typeObj != null) {
Class<?> cls = asClass(typeObj, seen);
if (cls != null) {
results.add(cls);
if (justFirst) {
return results;
}
}
}
}
return results;
}
public static List<Object> getTypeObjects(EObject eObj, boolean propagate, boolean strictMatch,
boolean justFirst, boolean complainIfNotFound, SeenSet<Object> seen) {
if (eObj == null) {
return null;
}
// return if we've already tried this eObj to avoid infinite recursion
Pair<Boolean, SeenSet<Object>> sp = Utils2.seen(eObj, true, seen);
if (sp.getKey()) {
return Collections.emptyList();
}
seen = sp.getValue();
ArrayList<Object> results = new ArrayList<Object>();
results.add(eObj.eClass());
if (justFirst) {
return results;
}
TreeSet<String> wordsForTypeSet = new TreeSet<String>(Arrays.asList(wordsForType));
boolean strictThisTime = true;
int sizeOfLast = 0;
// At most two loop iterations. First loop is for strict matches. Second
// is
// for non-strict.
while (true) {
// Get structural features whose names are words for "type"
List<EStructuralFeature> features = findStructuralFeaturesMatching(eObj, strictThisTime, false,
wordsForType);
// Ignore (remove) the features we already saw from the last loop.
if (sizeOfLast > 0) {
features = features.subList(sizeOfLast, features.size());
}
Object res = null;
// See if the eObj's instantiations of these structural features are
// Classes.
for (EStructuralFeature f : features) {
if (f != null) {
res = eObj.eGet(f);
// Class<?> cls = asClass( res, seen );
if (res != null) {
results.add(res);
if (justFirst) {
return results;
}
}
}
}
if (res == null) {
for (EObject eo : eObj.eContents()) {
// check if contained object's name indicates that it's a
// type
boolean found = false;
String myName = getName(eo);
if (myName != null && wordsForTypeSet.contains(getName(eo))) {
// Is the contained object itself represent a type?
// Class<?> cls = asClass( eo, seen );
if (eo != null) {
results.add(eo);
if (justFirst) {
return results;
}
found = true;
}
else {
// S
List<Object> oList = getValues(eo, Object.class, propagate, strictMatch,
justFirst, false, seen);
for (Object o : oList) {
// TODO -- REVIEW -- have already seen o from
// getValues()?!!
// cls = asClass( o, seen );
if (o != null) {
results.add(o);
if (justFirst) {
return results;
}
found = true;
}
}
}
found = true;
}
if (myName != null && !strictThisTime) {
// non-strict name check
for (String name : wordsForType) {
if (myName.toLowerCase().contains(name.toLowerCase())) {
// Class<?> cls = asClass( eo, seen ); // REVIEW
// seen correct here?
if (eo != null) {
results.add(eo);
if (justFirst) {
return results;
}
found = true;
// break;
}
}
}
}
if (!found)
// get type of value
{
if (!found && !strictThisTime) {
// get types of contents???
List<Object> resList = getTypeObjects(eo, propagate, strictMatch, justFirst,
false, seen);
if (!Utils2.isNullOrEmpty(resList)) {
if (justFirst) {
return resList;
}
results.addAll(resList);
}
}
}
}
}
if (strictMatch) {
break;
}
if (!strictThisTime) {
break;
}
// skip the ones we have already seen on the next loop
sizeOfLast = features.size(); // TODO -- REVIEW Didn't we get rid of
// lastSize??!
strictThisTime = false;
}
return results;
}
public static String[] wordsForType = new String[]{"Type", "Class", "Typename", "ClassName",
"DefaultType", "eClass", "Stereotype", "Metaclass"};
public static String[] eWordsForValue = new String[]{"value", "StringExpression", "OpaqueExpression",
"LiteralBoolean", "LiteralInteger", "LiteralNull", "LiteralSpecification", "LiteralString",
"LiteralUnlimitedNatural", "ElementValue", "Expression", "InstanceValue", "TimeExpression",
"TimeInterval", "Duration", "DurationInterval", "Interval",
"ValueSpecification", "propertyValue", "attributeValue", "referenceValue", "body", "result",
"defaultValue", "specification",
"literal", "instance"};
public static String[] oWordsForValue = new String[]{"value", "literal", "instance",
"Expression", "InstanceValue", "body", "result",
"StringExpression", "OpaqueExpression", "LiteralBoolean",
"LiteralInteger", "LiteralNull", "LiteralSpecification", "LiteralString",
"LiteralUnlimitedNatural", "ElementValue",
"defaultValue", "specification",
"ValueSpecification", "propertyValue", "attributeValue", "referenceValue",
"TimeExpression", "TimeInterval", "Duration", "DurationInterval", "Interval"};
public static List<Element> getRelationships(Element elem) {
LinkedHashSet<Element> elements = new LinkedHashSet<Element>();
elements.addAll(elem.get_relationshipOfRelatedElement());
elements.addAll(elem.get_directedRelationshipOfSource());
elements.addAll(elem.get_directedRelationshipOfTarget());
return Utils2.toList(elements);
}
public static boolean matches(String s, String pattern) {
if (s == pattern) {
return true;
}
if (pattern == null) {
return false;
}
if (s == null) {
return false;
}
if (s.equalsIgnoreCase(pattern)) {
return true;
}
if (s.matches(pattern)) {
return true;
}
List<String> list = getPossibleFieldNames(s);
list.remove(0);
for (String os : list) {
if (os.equalsIgnoreCase(pattern)) {
return true;
}
if (os.matches(pattern)) {
return true;
}
}
return false;
}
/**
* Determine
*
* @param obj
* @param pattern
* @return
*/
public static boolean matches(Object obj, Object pattern) {
return matches(obj, pattern, true, true);
}
public static boolean matches(Object obj, boolean useName, boolean useType, Object[] patterns) {
for (Object pattern : patterns) {
if (matches(obj, pattern, useName, useType)) {
return true;
}
}
return false;
}
public static boolean matches(Object obj, Object pattern, boolean useName, boolean useType) {
if (obj == pattern) {
return true;
}
if (pattern == null) {
return false;
}
if (obj == null) {
return false;
}
String oName = null; // obj's name
String oStr = null; // obj as String
Collection<Class<?>> oTypes = null; // obj's type's
String pStr = null; // pattern as String
String pName = null; // pattern's name
// don't use pType
if (obj.getClass().equals(String.class) && pattern.getClass().equals(String.class)) {
boolean m = matches((String) obj, (String) pattern);
if (m || !useType) {
return m;
}
}
else {
pStr = pattern.toString();
if (useName) {
oName = getName(obj);
if (Utils2.isNullOrEmpty(oName)) {
if (oName != null && oName.equals(pStr)) {
return true;
}
}
else {
if (matches(oName, pStr)) {
return true;
}
}
}
if (useName) {
pName = getName(pattern);
if (Utils2.isNullOrEmpty(oName)) {
if (oName != null && oName.equals(pName)) {
return true;
}
}
else {
if (matches(oName, pName)) {
return true;
}
}
}
oStr = obj.toString();
if (Utils2.isNullOrEmpty(oStr)) {
if (oStr != null && oStr.equals(pStr)) {
return true;
}
}
else {
if (matches(oStr, pStr)) {
return true;
}
if (useName && matches(oStr, pName)) {
return true;
}
}
}
if (useType) {
oTypes = getTypes(obj);
for (Class<?> t : oTypes) {
for (String oType : new String[]{t.getSimpleName(), t.getName()}) {
if (Utils2.isNullOrEmpty(oType)) {
if (oType != null && oType.equals(pStr)) {
return true;
}
}
else {
if (matches(oType, pStr)) {
return true;
}
if (useName && matches(oType, pName)) {
return true;
}
}
}
}
if (obj instanceof Element) {
Set<Stereotype> set = StereotypesHelper.getAllAssignedStereotypes(Utils2
.newList((Element) obj));
for (Stereotype sType : set) {
String sName = sType.getName();
if (matches(sName, pStr)) {
return true;
}
if (useName && matches(sName, pName)) {
return true;
}
}
}
}
return false;
}
@SuppressWarnings("unchecked")
public static Object collectOrFilter(CollectionAdder adder, Object obj, boolean collect, boolean onlyOne,
boolean useName, boolean useType, boolean useValue, boolean searchJava, Object... filters) {
if (obj instanceof Collection) {
return collectOrFilter(adder, (Collection<Object>) obj, collect, onlyOne, useName, useType,
useValue, searchJava, filters);
}
if (matches(obj, useName, useType, filters)) {
return obj;
}
return null;
}
@SuppressWarnings("unchecked")
public static List<Object> collectOrFilter(CollectionAdder adder, Collection<Object> elements,
boolean collect, boolean onlyOne, boolean useName, boolean useType, boolean useValue,
boolean searchJava, Object... filters) {
ArrayList<Object> resultList = new ArrayList<Object>();
if (filters == null || filters.length == 0 || (filters.length == 1 && filters[0] == null)) {
return Utils2.newList(elements.toArray());
}
for (Object elem : elements) {
boolean added = false;
for (Object filter : filters) {
if (matches(elem, filter, useName, useType)) {
added = adder.add(elem, resultList);
if (added) {
break;
}
}
}
if (onlyOne && added) {
break;
}
if (collect && elem instanceof Collection) {
--adder.defaultFlattenDepth;
List<Object> childRes = collectOrFilter(adder, (Collection<Object>) elem, collect, onlyOne,
useName, useType, useValue, searchJava, filters);
// collectOrFilter( (Collection< Object >)elem, collect,
// useName, useType, filters );
++adder.defaultFlattenDepth;
if (childRes != null) {
added = adder.add(childRes, resultList);
if (onlyOne && added) {
break;
}
}
}
}
return resultList;
}
}