/******************************************************************************* * Copyright (c) 2008 Olivier Moises * * 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: * Olivier Moises- initial API and implementation *******************************************************************************/ package org.eclipse.wazaabi.locationpaths.runtime; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.util.FeatureMap; import org.eclipse.wazaabi.locationpaths.model.Axis; import org.eclipse.wazaabi.locationpaths.model.BinaryExpression; import org.eclipse.wazaabi.locationpaths.model.EqualityExpression; import org.eclipse.wazaabi.locationpaths.model.Expression; import org.eclipse.wazaabi.locationpaths.model.IntegerExpression; import org.eclipse.wazaabi.locationpaths.model.LiteralExpression; import org.eclipse.wazaabi.locationpaths.model.LocationPath; import org.eclipse.wazaabi.locationpaths.model.Operator; import org.eclipse.wazaabi.locationpaths.model.Pointer; import org.eclipse.wazaabi.locationpaths.model.Step; public class Evaluator { public static Object getSingleObject(Object context, String path) { List<Pointer<?>> pointers = LocationSelector.select(context, path); if (!pointers.isEmpty()) { List<?> result = Evaluator.evaluate(pointers.get(0)); if (result.isEmpty()) return null; return result.get(0); } return null; } public static List<?> getObjects(Object context, String path) { List<Object> result = new ArrayList<Object>(); Iterator<Pointer<?>> selectionIterator = LocationSelector.select( context, path).iterator(); while (selectionIterator.hasNext()) { Pointer<?> pointer = selectionIterator.next(); Iterator<Object> evaluationIterator = Evaluator.evaluate(pointer) .iterator(); while (evaluationIterator.hasNext()) { Object item = evaluationIterator.next(); if (!result.contains(item)) result.add(item); } } return result; } public static List evaluate(Pointer<?> pointer) { if (pointer == null) return Collections.emptyList(); return evaluate(pointer.getContext(), pointer.getStep()); } // TODO : manage unsettable structural feature protected static List evaluate(Object context, Step step) { List pointers = evaluate(context, step.getAxis(), step.getNameTest()); if (!step.getPredicates().isEmpty()) pointers = filter(pointers, step.getPredicates()); return removeDuplicates(pointers); } protected static List evaluatePureJavaObject(Object context, int axis, String nameTest) { if (context == null) return Collections.emptyList(); switch (axis) { case Axis.CHILD:/* * { List result = new ArrayList(30); Iterator * contentIterator = context.eContents().iterator(); * while (contentIterator.hasNext()) { EObject child = * (EObject) contentIterator.next(); if ((nameTest != * null && nameTest.equals(child.eClass() .getName())) * || nameTest == null || "*".equals(nameTest)) if * (child != null) result.add(child); } return result; } */ break; case Axis.ATTRIBUTE: break; case Axis.REFERENCE: break; case Axis.VARIABLE: { try { // TODO : not finished, the name of the method will change Method getValueMethod = context.getClass().getMethod( "get", new Class[] { String.class }); //$NON-NLS-1$ if (getValueMethod != null) { Object value = getValueMethod.invoke(context, new Object[] { nameTest }); if (value instanceof List) return (List) value; else if (value instanceof Object) { List returnedAsList = new ArrayList(1); returnedAsList.add(value); return returnedAsList; } } } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { // Nothing to do here } catch (IllegalArgumentException e) { // Nothing to do here } catch (IllegalAccessException e) { e.printStackTrace(); // Nothing to do here } catch (InvocationTargetException e) { // Nothing to do here } } break; case Axis.SELF: if (nameTest == null) { List result = new ArrayList(1); result.add(context); return result; } break; } return Collections.emptyList(); } /** * Evaluates the given context according to this axis and this nameTest * * @param context * @param axis * @param nameTest * @return A list which cannot be null. */ protected static List evaluate(EObject eContext, int axis, String nameTest) { if (eContext == null) return Collections.emptyList(); switch (axis) { case Axis.CHILD: { List result = new ArrayList(30); Iterator contentIterator = eContext.eContents().iterator(); while (contentIterator.hasNext()) { EObject child = (EObject) contentIterator.next(); if ((nameTest != null && nameTest.equals(child.eClass() .getName())) || nameTest == null || "*".equals(nameTest)) if (child != null) result.add(child); } return result; } case Axis.DESCENDANT_OR_SELF: break; case Axis.PARENT: if (nameTest == null && eContext.eContainer() != null) { List result = new ArrayList(1); result.add(eContext.eContainer()); return result; } break; case Axis.CLASS: if (nameTest == null) { List result = new ArrayList(1); result.add(eContext.eClass()); return result; } break; case Axis.PACKAGE: if (nameTest == null) { List result = new ArrayList(1); if (eContext instanceof EClass) result.add(((EClass) eContext).getEPackage()); else result.add(eContext.eClass().getEPackage()); return result; } break; case Axis.ATTRIBUTE: { if (nameTest == null || "*".equals(nameTest)) //$NON-NLS-1$ return getAllEAttributesContentAsList(eContext); EStructuralFeature attribute = eContext.eClass() .getEStructuralFeature(nameTest); if (attribute instanceof EAttribute) return getFeatureContentAsList(eContext, attribute); } break; case Axis.REFERENCE: { if (nameTest == null || "*".equals(nameTest)) //$NON-NLS-1$ return getAllEReferencesContentAsList(eContext); EStructuralFeature reference = eContext.eClass() .getEStructuralFeature(nameTest); if (reference instanceof EReference) return getFeatureContentAsList(eContext, reference); } break; case Axis.VARIABLE: { try { // TODO : not finished, the name of the method will change Method getValueMethod = eContext.getClass().getMethod( "get", new Class[] { String.class }); //$NON-NLS-1$ if (getValueMethod != null) { Object value = getValueMethod.invoke(eContext, new Object[] { nameTest }); if (value instanceof List) return (List) value; else if (value instanceof Object) { List returnedAsList = new ArrayList(1); returnedAsList.add(value); return returnedAsList; } } } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { // Nothing to do here } catch (IllegalArgumentException e) { // Nothing to do here } catch (IllegalAccessException e) { e.printStackTrace(); // Nothing to do here } catch (InvocationTargetException e) { // Nothing to do here } } break; case Axis.SELF: if (nameTest == null) { List result = new ArrayList(1); result.add(eContext); return result; } break; } return Collections.emptyList(); } protected static boolean hasClassOrInterfaceName(String name, Object object) { if (object == null || name == null || name.length() == 0) return false; if (object.getClass().getSimpleName().equals(name)) return true; for (Class<?> clazz : object.getClass().getInterfaces()) { System.out.println(clazz.getSimpleName()); if (name.equals(clazz.getSimpleName())) return true; } return false; } protected static List<?> evaluate(List<?> context, int axis, String nameTest) { if (context == null) return Collections.emptyList(); switch (axis) { case Axis.CHILD: { List<Object> result = new ArrayList<Object>(30); Iterator<?> contentIterator = context.iterator(); while (contentIterator.hasNext()) { Object child = contentIterator.next(); if ("*".equals(nameTest) || hasClassOrInterfaceName(nameTest, child)) if (child != null) result.add(child); } return result; } // case Axis.DESCENDANT_OR_SELF: // break; // case Axis.PARENT: // break; // case Axis.CLASS: // if (nameTest == null) { // List<String> result = new ArrayList<String>(1); // result.add(context.getClass().getName()); // return result; // } // break; // case Axis.PACKAGE: // if (nameTest == null) { // List result = new ArrayList(1); // if (eContext instanceof EClass) // result.add(((EClass) eContext).getEPackage()); // else // result.add(eContext.eClass().getEPackage()); // return result; // } // break; // case Axis.ATTRIBUTE: { // if (nameTest == null || "*".equals(nameTest)) //$NON-NLS-1$ // return getAllEAttributesContentAsList(eContext); // EStructuralFeature attribute = eContext.eClass() // .getEStructuralFeature(nameTest); // if (attribute instanceof EAttribute) // return getFeatureContentAsList(eContext, attribute); // } // break; // case Axis.REFERENCE: { // if (nameTest == null || "*".equals(nameTest)) //$NON-NLS-1$ // return getAllEReferencesContentAsList(eContext); // EStructuralFeature reference = eContext.eClass() // .getEStructuralFeature(nameTest); // if (reference instanceof EReference) // return getFeatureContentAsList(eContext, reference); // } // break; // case Axis.VARIABLE: { // try { // // TODO : not finished, the name of the method will change // Method getValueMethod = eContext.getClass().getMethod( // "get", new Class[] { String.class }); //$NON-NLS-1$ // if (getValueMethod != null) { // Object value = getValueMethod.invoke(eContext, // new Object[] { nameTest }); // if (value instanceof List) // return (List) value; // else if (value instanceof Object) { // List returnedAsList = new ArrayList(1); // returnedAsList.add(value); // return returnedAsList; // } // } // } catch (SecurityException e) { // e.printStackTrace(); // } catch (NoSuchMethodException e) { // // Nothing to do here // } catch (IllegalArgumentException e) { // // Nothing to do here // } catch (IllegalAccessException e) { // e.printStackTrace(); // // Nothing to do here // } catch (InvocationTargetException e) { // // Nothing to do here // } // } // break; // case Axis.SELF: // if (nameTest == null) { // List result = new ArrayList(1); // result.add(eContext); // return result; // } // break; } return Collections.emptyList(); } protected static List<?> evaluate(Object context, int axis, String nameTest) { if (context == null) return Collections.emptyList(); if (context instanceof EObject) return evaluate((EObject) context, axis, nameTest); if (context instanceof FeatureMap) return FeatureMapEvaluator.evaluate((FeatureMap) context, axis, nameTest); if (context instanceof List<?>) return evaluate((List<?>) context, axis, nameTest); else return evaluatePureJavaObject(context, axis, nameTest); } protected static List getAllEAttributesContentAsList(EObject object) { List result = new ArrayList(30); Iterator attributeIterator = object.eClass().getEAllAttributes() .iterator(); while (attributeIterator.hasNext()) result.addAll(getFeatureContentAsList(object, (EAttribute) attributeIterator.next())); return result; } protected static List<?> getAllEReferencesContentAsList(EObject object) { List<Object> result = new ArrayList<Object>(30); Iterator<EReference> referenceIterator = object.eClass() .getEAllReferences().iterator(); while (referenceIterator.hasNext()) result.addAll(getFeatureContentAsList(object, referenceIterator.next())); return result; } protected static List<?> getFeatureContentAsList(EObject object, EStructuralFeature feature) { Object value = object.eGet(feature); if (value instanceof List<?>) return (List<?>) value; else if (value instanceof Object) { List<Object> result = new ArrayList<Object>(1); result.add(value); return result; } return Collections.emptyList(); } /** * Filters a list of Java object using the given list of predicates. * * @param rawChildren * A list of Java objects * @param predicate * The list of predicates used to filter the list. * @return A List of object, the list can be empty. */ protected static List filter(List rawChildren, List<Expression> predicates) { List result = rawChildren; for (int i = 0; i < predicates.size(); i++) { result = filter(result, predicates.get(i)); } return result; } /** * Filters a list of Object using the predicate. * * @param rawChildren * A list of Java objects * @param predicate * The predicate used to filter the list. * @return A List of object, the list can be empty. */ protected static List filter(List rawChildren, Expression predicate) { // TODO provisional if (predicate instanceof IntegerExpression) return filter(rawChildren, (IntegerExpression) predicate); else if (predicate instanceof EqualityExpression) return filter(rawChildren, (EqualityExpression) predicate); // else if (predicate instanceof BinaryExpression) // return filter(rawChildren, (BinaryExpression) predicate); return rawChildren; } /** * Gets and returns the element of the list whose index is given by the * predicate. * * @param rawChildren * A list of objects. * @param predicate * An predicate containing the 0 based index of the returned * element. * @return A List containing only one element when found, an empty list * otherwise. */ protected static List filter(List rawChildren, IntegerExpression predicate) { // in xpath, [2] is equivalent to [position()==2] if (rawChildren.isEmpty() || predicate.getValue() > rawChildren.size()) return Collections.emptyList(); List result = new ArrayList(1); result.add(rawChildren.get(predicate.getValue())); return result; } protected static List filter(List rawChildren, BinaryExpression predicate) { List result = new ArrayList(rawChildren.size()); return result; } protected static List filter(List rawChildren, EqualityExpression predicate) { if (predicate.getOperator() == Operator.EQUAL) { LocationPath locationPath = null; Expression otherExpression = null; if (predicate.getLeftOperand() instanceof LocationPath) { locationPath = (LocationPath) predicate.getLeftOperand(); otherExpression = predicate.getRightOperand(); } else if (predicate.getRightOperand() instanceof LocationPath) { locationPath = (LocationPath) predicate.getRightOperand(); otherExpression = predicate.getLeftOperand(); } if (locationPath.getSteps().size() == 1 && ((Step) locationPath.getSteps().get(0)).getAxis() == Axis.ATTRIBUTE) { final String attributeName = ((Step) locationPath.getSteps() .get(0)).getNameTest(); if (otherExpression instanceof LiteralExpression && ((LiteralExpression) otherExpression).getValue() != null) { final String value = ((LiteralExpression) otherExpression) .getValue(); return filterByStringEAttributeValue(rawChildren, attributeName, value); } else if (otherExpression instanceof IntegerExpression) { final int value = ((IntegerExpression) otherExpression) .getValue(); return filterByIntegerEAttributeValue(rawChildren, attributeName, value); } } } return Collections.emptyList(); } public static List filterByStringEAttributeValue(List rawChildren, String attributeName, String value) { List result = new ArrayList(rawChildren.size()); Iterator iterator = rawChildren.iterator(); while (iterator.hasNext()) { Object item = iterator.next(); if (item instanceof EObject) { EStructuralFeature feature = ((EObject) item).eClass() .getEStructuralFeature(attributeName); if (feature instanceof EAttribute && ((EAttribute) feature).getEAttributeType() == EcorePackage.Literals.ESTRING) { if (value.equals(((EObject) item).eGet(feature))) result.add(item); } } } return result; } public static List filterByIntegerEAttributeValue(List rawChildren, String attributeName, int value) { List result = new ArrayList(rawChildren.size()); Iterator iterator = rawChildren.iterator(); while (iterator.hasNext()) { Object item = iterator.next(); if (item instanceof EObject) { EStructuralFeature feature = ((EObject) item).eClass() .getEStructuralFeature(attributeName); if (feature instanceof EAttribute) { switch (((EAttribute) feature).getEAttributeType() .getClassifierID()) { case EcorePackage.EINT: case EcorePackage.ELONG: case EcorePackage.ESHORT: if (new Integer(value).equals(((EObject) item) .eGet(feature))) result.add(item); break; } } } } return result; } /** * Iterates over the given list and ensures that no value can be duplicated. * * @param rawChildren * The initial list * @return A non null list of Object. */ protected static List<?> removeDuplicates(List<?> rawChildren) { List result = new ArrayList(rawChildren.size()); Iterator rawChildrenIterator = rawChildren.iterator(); while (rawChildrenIterator.hasNext()) { Object item = rawChildrenIterator.next(); if (!result.contains(item)) result.add(item); } return result; } }