| /* |
| * Copyright (c) 2005, 2008 Sven Efftinge 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: |
| * Sven Efftinge - Initial API and implementation |
| * Artem Tikhomirov (Borland) - Migration to OCL expressions |
| */ |
| package org.eclipse.gmf.internal.xpand.util; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.List; |
| |
| import org.eclipse.emf.ecore.EClassifier; |
| import org.eclipse.gmf.internal.xpand.model.AmbiguousDefinitionException; |
| import org.eclipse.gmf.internal.xpand.model.XpandDefinition; |
| import org.eclipse.ocl.ecore.EcoreEnvironment; |
| |
| /** |
| * @author Sven Efftinge |
| * @author Arno Haase |
| */ |
| public class PolymorphicResolver { |
| |
| public static XpandDefinition filterDefinition(final HashMap<XpandDefinition, List<EClassifier>> resolvedDefs, EClassifier targetType, List<EClassifier> paramTypes, EcoreEnvironment env) throws AmbiguousDefinitionException { |
| final List<EClassifier> allParams = new ArrayList<EClassifier>(); |
| allParams.add(targetType); |
| allParams.addAll(paramTypes); |
| |
| final TypesComparator typesComparator = new TypesComparator(env); |
| |
| final List<XpandDefinition> candidateDefinition = new ArrayList<XpandDefinition>(); |
| for (XpandDefinition def : resolvedDefs.keySet()) { |
| final List<? extends EClassifier> featureParamTypes = resolvedDefs.get(def); |
| if ((featureParamTypes.size() == allParams.size()) |
| && (typesComparator .compare(featureParamTypes, allParams) >= 0)) { |
| candidateDefinition.add(def); |
| } |
| } |
| final Comparator<XpandDefinition> comparator = new Comparator<XpandDefinition>() { |
| public int compare(XpandDefinition d1, XpandDefinition d2) { |
| return typesComparator.compare(resolvedDefs.get(d1), resolvedDefs.get(d2)); |
| } |
| }; |
| try { |
| return filterWithComparator(candidateDefinition, comparator); |
| } catch (IllegalStateException ex) { |
| throw new AmbiguousDefinitionException(candidateDefinition.get(0), candidateDefinition.get(1)); |
| } |
| } |
| |
| /** |
| * @throws IllegalStateException when there are more than one candidates with same priority |
| */ |
| private static <T> T filterWithComparator(List<T> candidates, Comparator<T> comparator) throws IllegalStateException { |
| if (candidates.size() == 1) { |
| return candidates.get(0); |
| } else if (candidates.isEmpty()) { |
| return null; |
| } else { |
| // sort features by specialization |
| Collections.sort(candidates, comparator); |
| |
| if (comparator.compare(candidates.get(1), candidates.get(0)) > 0) { |
| return candidates.get(0); |
| } else { |
| throw new IllegalStateException(); |
| } |
| } |
| } |
| |
| } |