/** Return the map of name to property for a type. */
 protected Map<String, P> getName2Property(C type) {
   Map<String, P> name2property = type2name2property.get(type);
   if (name2property == null) {
     name2property = new HashMap<String, P>();
     type2name2property.put(type, name2property);
     List<P> allProperties = getAttributes(type);
     for (P candidateProperty : allProperties) {
       String name = uml.getName(candidateProperty);
       P oldProperty = name2property.get(name);
       if (oldProperty == null) {
         name2property.put(name, candidateProperty);
       } else {
         C candidateOwner = uml.getOwningClassifier(candidateProperty);
         Collection<? extends C> candidateSupertypes = uml.getAllSupertypes(candidateOwner);
         C oldOwner = uml.getOwningClassifier(oldProperty);
         if (candidateSupertypes.contains(oldOwner)) {
           name2property.put(name, candidateProperty);
         } else {
           Collection<? extends C> oldSupertypes = uml.getAllSupertypes(oldOwner);
           if (!oldSupertypes.contains(candidateOwner)) {; // This should not happen
           }
         }
       }
     }
   }
   return name2property;
 }
 /**
  * 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;
   }
 }
 /** Return true if requiredParameters is an exact match for candidateParameters. */
 protected boolean exactlyMatches(
     List<? extends PM> requiredParameters, List<? extends PM> candidateParameters) {
   int iMax = requiredParameters.size();
   if (iMax != candidateParameters.size()) {
     return false;
   }
   for (int i = 0; i < iMax; i++) {
     PM requiredParameter = requiredParameters.get(i);
     PM candidateParameter = candidateParameters.get(i);
     C requiredType = uml.getOCLType(requiredParameter);
     C candidateType = uml.getOCLType(candidateParameter);
     if (requiredType != candidateType) {
       return false;
     }
   }
   return true;
 }
Exemple #4
0
  /**
   * Tests that the {@link UMLReflection} API provides the correct owner of an additional attribute.
   */
  public void test_defExpression_attribute_owner() {
    helper.setContext(apple);

    try {
      Property p = helper.defineAttribute("fallen : Boolean = " + "tree.oclIsUndefined()");

      UMLReflection<?, Classifier, ?, ?, ?, ?, ?, ?, ?, ?> uml =
          ocl.getEnvironment().getUMLReflection();

      // sanity check
      assertSame(apple, uml.getOwningClassifier(apple_label));

      // check the owner of the additional operation
      assertSame(apple, uml.getOwningClassifier(p));
    } catch (Exception e) {
      fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
    }
  }
  @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;
    }
  }
Exemple #6
0
  /**
   * Tests that the {@link UMLReflection} API provides the correct owner of an additional operation.
   */
  public void test_defExpression_operation_owner() {
    helper.setContext(fruit);

    try {
      Operation o =
          helper.defineOperation(
              "bestColor(c : Color) : Color = "
                  + "if self.color = Color::black then c else self.color endif");

      UMLReflection<?, Classifier, ?, ?, ?, ?, ?, ?, ?, ?> uml =
          ocl.getEnvironment().getUMLReflection();

      // sanity check
      assertSame(fruit, uml.getOwningClassifier(fruit_ripen));

      // check the owner of the additional operation
      assertSame(fruit, uml.getOwningClassifier(o));
    } catch (Exception e) {
      fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
    }
  }
Exemple #7
0
  /** Tests the parsing the def expression for static attributes and operations. */
  public void test_defExpression_static() {
    try {
      Environment<
              Package,
              Classifier,
              Operation,
              Property,
              EnumerationLiteral,
              Parameter,
              State,
              CallOperationAction,
              SendSignalAction,
              Constraint,
              Class,
              EObject>
          env = ocl.getEnvironment();
      UMLReflection<
              Package,
              Classifier,
              Operation,
              Property,
              EnumerationLiteral,
              Parameter,
              State,
              CallOperationAction,
              SendSignalAction,
              Constraint>
          umlReflection = env.getUMLReflection();

      ParsingOptions.setOption(ocl.getEnvironment(), ParsingOptions.SUPPORT_STATIC_FEATURES, true);
      parseDef(
          "package ocltest context Fruit "
              + "def: bestColor1() : Color = null "
              + "static def: bestColor2() : Color = null "
              + "def: goodColor1 : Color = null "
              + "static def: goodColor2 : Color = null "
              + "endpackage");
      Operation operation1 = env.lookupOperation(fruit, "bestColor1", null);
      assertNotNull(operation1);
      assertEquals(false, umlReflection.isStatic(operation1));
      Operation operation2 = env.lookupOperation(fruit, "bestColor2", null);
      assertNotNull(operation2);
      assertEquals(true, umlReflection.isStatic(operation2));
      Property property1 = env.lookupProperty(fruit, "goodColor1");
      assertNotNull(property1);
      assertEquals(false, umlReflection.isStatic(property1));
      Property property2 = env.lookupProperty(fruit, "goodColor2");
      assertNotNull(property2);
      assertEquals(true, umlReflection.isStatic(property2));

      ParsingOptions.setOption(ocl.getEnvironment(), ParsingOptions.SUPPORT_STATIC_FEATURES, false);
      try {
        ocl.parse(
            new OCLInput(
                "package ocltest context Fruit "
                    + "def: bestColor3() : Color = null "
                    + "static def: bestColor4() : Color = null "
                    + "endpackage"));
        fail("Should have failed to parse the unsupported static");
      } catch (ParserException e) {
        // success!
        assertEquals(OCLMessages.UnsupportedStatic_ERROR_, e.getMessage());
        System.out.println("Got the expected exception: " + e.getLocalizedMessage());
      }
    } catch (Exception e) {
      fail("Failed to parse or evaluate: " + e.getLocalizedMessage());
    }
  }
 /** 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;
 }