/** * Return the operation from the name2operationOrOperations cache that matches operation. Returns * null if there is no operation or more than one. * * @param name2operationOrOperations * @param operation */ protected O getExactMatchingOperation( Map<String, Object> name2operationOrOperations, O operation) { String requiredName = uml.getName(operation); List<PM> requiredParameters = uml.getParameters(operation); Object candidateOperationOrOperations = name2operationOrOperations.get(requiredName); if (candidateOperationOrOperations instanceof List<?>) { O matchingOperation = null; @SuppressWarnings("unchecked") List<O> candidateOperations = (List<O>) candidateOperationOrOperations; for (O candidateOperation : candidateOperations) { List<PM> candidateParameters = uml.getParameters(candidateOperation); if (exactlyMatches(requiredParameters, candidateParameters)) { if (matchingOperation == null) { matchingOperation = candidateOperation; } else { return null; // Ambiguity detected } } } return matchingOperation; } else if (candidateOperationOrOperations != null) { @SuppressWarnings("unchecked") O candidateOperation = (O) candidateOperationOrOperations; List<PM> candidateParameters = uml.getParameters(candidateOperation); if (exactlyMatches(requiredParameters, candidateParameters)) { return candidateOperation; } else { return null; } } else { return null; } }
@Override protected List<O> getBestMatchingOperations( C owner, String name, List<? extends TypedElement<C>> args) { if (bypass) { return super.getBestMatchingOperations(owner, name, args); } Map<String, Object> name2operationOrOperations = getName2OperationOrOperations(owner); Object candidateOperationOrOperations = name2operationOrOperations.get(name); if (candidateOperationOrOperations instanceof List<?>) { List<O> matches = null; @SuppressWarnings("unchecked") List<O> candidateOperations = (List<O>) candidateOperationOrOperations; int bestExactitude = 0; for (O oper : candidateOperations) { int exactitude = matchArgsWithExactitude(owner, uml.getParameters(oper), args); if (exactitude >= bestExactitude) { if (exactitude > bestExactitude) { if (matches != null) { matches.clear(); } bestExactitude = exactitude; } if (matches == null) { // assume a small number of redefinitions matches = new java.util.ArrayList<O>(3); } matches.add(oper); } } return matches; } else if (candidateOperationOrOperations != null) { @SuppressWarnings("unchecked") O candidateOperation = (O) candidateOperationOrOperations; int exactitude = matchArgsWithExactitude(owner, uml.getParameters(candidateOperation), args); if (exactitude >= 0) { return Collections.singletonList(candidateOperation); } else { return null; } } else { return null; } }
/** Return the map of name to operator or list of operations for a type. */ protected Map<String, Object> getName2OperationOrOperations(C type) { Map<String, Object> name2operationOrOperations = type2name2operationOrOperations.get(type); if (name2operationOrOperations == null) { name2operationOrOperations = new HashMap<String, Object>(); type2name2operationOrOperations.put(type, name2operationOrOperations); List<O> allOperations = getOperations(type); for (O candidateOperation : allOperations) { String name = uml.getName(candidateOperation); Object overloadOrOverloads = name2operationOrOperations.get(name); if (overloadOrOverloads == null) { name2operationOrOperations.put(name, candidateOperation); } else { List<O> overloads; if (overloadOrOverloads instanceof List<?>) { @SuppressWarnings("unchecked") List<O> castOperations = (List<O>) overloadOrOverloads; overloads = castOperations; } else { overloads = new ArrayList<O>(); name2operationOrOperations.put(name, overloads); @SuppressWarnings("unchecked") O castOperation = (O) overloadOrOverloads; overloads.add(castOperation); } C candidateOwner = uml.getOwningClassifier(candidateOperation); Collection<? extends C> candidateSupertypes = uml.getAllSupertypes(candidateOwner); List<PM> candidateParameters = uml.getParameters(candidateOperation); int iMax = candidateParameters.size(); int j = overloads.size(); while (--j >= 0) { // Reverse count to allow remove() O oldOperation = overloads.get(j); List<PM> oldParameters = uml.getParameters(oldOperation); if (iMax == oldParameters.size()) { int i = 0; for (; i < iMax; i++) { PM candidateParameter = candidateParameters.get(i); PM oldParameter = oldParameters.get(i); C oldType = uml.getOCLType(oldParameter); C candidateType = uml.getOCLType(candidateParameter); if (oldType != candidateType) { break; } } if (i >= iMax) { C oldOwner = uml.getOwningClassifier(oldOperation); if (candidateSupertypes.contains(oldOwner)) { overloads.remove(j); } else { Collection<? extends C> oldSupertypes = uml.getAllSupertypes(oldOwner); if (oldSupertypes.contains(candidateOwner)) { break; } } } } } if (j < 0) { overloads.add(candidateOperation); } } } } return name2operationOrOperations; }