예제 #1
0
 public void DealClassifier(org.eclipse.uml2.uml.Classifier c1, RefOntoUML.Classifier c2) {
   DealNamedElement(c1, c2);
   // Important for Generalization, Property
   RelateElements(c1, c2);
   // isAbstract
   c2.setIsAbstract(c1.isAbstract());
 }
  public SignatureFacade createConstructorFacade(InstanceCreationExpression exp) throws Exception {
    List<TypeExpression> arguments = new ArrayList<TypeExpression>();
    Map<String, TypeExpression> argumentsMap = new HashMap<String, TypeExpression>();

    if (exp.getTuple().getInstanceCreationTupleElement() != null) {
      for (InstanceCreationTupleElement tupleElement :
          exp.getTuple().getInstanceCreationTupleElement()) {
        TypeExpression typeOfArgument =
            new TypeUtils().getTypeOfExpression(tupleElement.getObject());
        if (typeOfArgument.getTypeFacade() instanceof ErrorTypeFacade)
          throw new TypeInferenceException(typeOfArgument);
        arguments.add(typeOfArgument);
        argumentsMap.put(tupleElement.getRole(), typeOfArgument);
      }
    }

    // first try to determine if the expression directly refers to a Class or a DataType
    TypeFacade cddClassifier = TypeFacadeFactory.eInstance.createVoidFacade(exp.getConstructor());
    boolean errorInResolutionOfClassifier = false;
    if (cddClassifier instanceof ErrorTypeFacade) {
      errorInResolutionOfClassifier = true;
    } else {
      Classifier referencedType = cddClassifier.extractActualType();
      if (referencedType instanceof PrimitiveType) {
        throw new Exception("Constructor invocations do not apply to primitive types");
      }
      if (referencedType instanceof Enumeration) {
        throw new Exception("Constructor invocations do not apply to enumerations");
      }
      if (referencedType.isAbstract()) {
        throw new Exception("Abstract classifiers cannot be instantiated");
      }

      // The classifier has been resolved. Must determine if arguments match with possible
      // constructors
      if (referencedType instanceof org.eclipse.uml2.uml.Class) {
        List<EObject> visibleConstructor =
            AlfScopeProvider.scopingTool
                .getVisibleOperationsOrBehaviors(referencedType)
                .resolveByName(referencedType.getName());
        if (visibleConstructor.size() > 1) {
          // try to match with arguments
          // if does not match, raise an exception
          List<SignatureFacade> visibleConstructorSignatures = new ArrayList<SignatureFacade>();
          for (EObject cddConstructor : visibleConstructor) {
            SignatureFacade cddConstructorSignature =
                SignatureFacadeFactory.eInstance.createSignatureFacade(cddConstructor);
            if (cddConstructorSignature.isAConstructor())
              visibleConstructorSignatures.add(cddConstructorSignature);
          }
          List<SignatureFacade> matchingSignatures =
              SignatureFacade.findNearestSignature(arguments, visibleConstructorSignatures);
          if (matchingSignatures.size() > 1) {
            String errorMessage = referencedType.getName() + "(";
            boolean first = true;
            for (TypeExpression arg : arguments) {
              if (first) first = false;
              else errorMessage += ", ";
              errorMessage += arg.getLabel();
            }
            errorMessage += ") resolves to multiple constructors";
            throw new Exception(errorMessage);
          } else if (matchingSignatures.size() == 0) {
            String errorMessage = "Constructor " + referencedType.getName() + "(";
            boolean first = true;
            for (TypeExpression arg : arguments) {
              if (first) first = false;
              else errorMessage += ", ";
              errorMessage += arg.getLabel();
            }
            errorMessage += ") is undefined";
            throw new Exception(errorMessage);
          } else { // exactly one match
            return matchingSignatures.get(0);
          }
        } else if (visibleConstructor.size() == 0) {
          if (arguments.size() > 0) {
            // Throw an exception
            String errorMessage = "Constructor " + referencedType.getName() + "(";
            boolean first = true;
            for (TypeExpression t : arguments) {
              if (first) first = false;
              else errorMessage += ", ";
              errorMessage += t.getLabel();
            }
            errorMessage += ") is undefined";
            throw new Exception(errorMessage);
          }
          return new DefaultConstructorFacade((Class) referencedType);
        } else { // exactly one constructor found
          // Tries to determine if arguments match
          SignatureFacade constructor = createSignatureFacade(visibleConstructor.get(0));
          if (!constructor.isAConstructor()) {
            // Throw an exception
            String errorMessage = "Constructor " + referencedType.getName() + "(";
            boolean first = true;
            for (TypeExpression t : arguments) {
              if (first) first = false;
              else errorMessage += ", ";
              errorMessage += t.getLabel();
            }
            errorMessage += ") is undefined";
            throw new Exception(errorMessage);
          }
          String potentialErrorMessage = constructor.isCompatibleWithMe(argumentsMap);
          if (potentialErrorMessage.length() == 0) return constructor;
          else throw new Exception(potentialErrorMessage);
        }
      } else if (referencedType instanceof DataType) { // This is a data type.
        // must match arguments with visible properties of the data type
        SignatureFacade defaultDataTypeConstructor =
            new DefaultConstructorFacade((DataType) referencedType);
        String errorMessage = defaultDataTypeConstructor.isCompatibleWithMe(argumentsMap);
        if (!(errorMessage.length() == 0)) throw new Exception(errorMessage);
        else return defaultDataTypeConstructor;
      }
    }

    if (errorInResolutionOfClassifier) {
      // We can try again, but considering that:
      // - the last element in the qualified name as the name of a constructor
      // - the element before the last element is a class name

      if (exp.getConstructor().getRemaining() == null)
        throw new Exception("Constructor " + exp.getConstructor().getId() + " is undefined");

      QualifiedNameWithBinding remaining = exp.getConstructor();
      QualifiedNameWithBinding cddClassName = exp.getConstructor();
      QualifiedNameWithBinding cddConstructorName = exp.getConstructor();
      EObject previousPackage = null;

      while (cddConstructorName.getRemaining() != null) {
        cddClassName = cddConstructorName;
        cddConstructorName = cddConstructorName.getRemaining();
      }

      if (remaining != cddClassName) {
        List<EObject> visiblePackages =
            AlfScopeProvider.scopingTool.getVisiblePackages(exp).resolveByName(remaining.getId());
        if (visiblePackages.isEmpty()) {
          throw new Exception("Could not resolve package " + remaining.getId());
        } else if (visiblePackages.size() > 1) {
          throw new Exception(remaining.getId() + " resolves to multiple packages");
        } else {
          List<EObject> nestedVisiblePackages;
          previousPackage = visiblePackages.get(0);
          remaining = remaining.getRemaining();
          while (remaining != cddClassName) {
            nestedVisiblePackages =
                AlfScopeProvider.scopingTool
                    .getVisiblePackages(previousPackage)
                    .resolveByName(remaining.getId());
            if (nestedVisiblePackages.isEmpty()) {
              throw new Exception("Could not resolve package " + remaining.getId());
            } else if (nestedVisiblePackages.size() > 1) {
              throw new Exception(remaining.getId() + " resolves to multiple packages");
            }
            previousPackage = nestedVisiblePackages.get(0);
            remaining = remaining.getRemaining();
          }
        }
      }

      // At this point, the (potential) path has been validated
      // cddClassName should resolve to a classifier
      List<EObject> visibleClassifiers = null;
      EObject resolvedClassifier = null;
      if (previousPackage != null)
        visibleClassifiers =
            AlfScopeProvider.scopingTool
                .getVisibleClassifiers(previousPackage)
                .resolveByName(cddClassName.getId());
      else
        visibleClassifiers =
            AlfScopeProvider.scopingTool
                .getVisibleClassifiers(exp)
                .resolveByName(cddClassName.getId());
      if (visibleClassifiers.isEmpty()) {
        throw new Exception("Could not resolve classifier " + cddClassName.getId());
      } else if (visibleClassifiers.size() > 1) {
        throw new Exception(remaining.getId() + " resolves to multiple classifiers.");
      } else {
        resolvedClassifier = visibleClassifiers.get(0);
      }
      List<EObject> visibleConstructor =
          AlfScopeProvider.scopingTool
              .getVisibleOperationsOrBehaviors(resolvedClassifier)
              .resolveByName(cddConstructorName.getId());
      if (visibleConstructor.size() > 1) {
        // try to match with arguments
        // if does not match, raise an exception
        List<SignatureFacade> visibleConstructorSignatures = new ArrayList<SignatureFacade>();
        for (EObject cddConstructor : visibleConstructor) {
          SignatureFacade cddConstructorSignature =
              SignatureFacadeFactory.eInstance.createSignatureFacade(cddConstructor);
          if (cddConstructorSignature.isAConstructor())
            visibleConstructorSignatures.add(cddConstructorSignature);
        }
        List<SignatureFacade> matchingSignatures =
            SignatureFacade.findNearestSignature(arguments, visibleConstructorSignatures);
        if (matchingSignatures.size() > 1) {
          String errorMessage = cddConstructorName.getId() + "(";
          boolean first = true;
          for (TypeExpression arg : arguments) {
            if (first) first = false;
            else errorMessage += ", ";
            errorMessage += arg.getLabel();
          }
          errorMessage += ") resolves to multiple constructors";
          throw new Exception(errorMessage);
        } else if (matchingSignatures.size() == 0) {
          String errorMessage = "Constructor " + cddConstructorName.getId() + "(";
          boolean first = true;
          for (TypeExpression arg : arguments) {
            if (first) first = false;
            else errorMessage += ", ";
            errorMessage += arg.getLabel();
          }
          errorMessage += ") is undefined";
          throw new Exception(errorMessage);
        } else { // exactly one match
          return matchingSignatures.get(0);
        }
      } else if (visibleConstructor.size() == 0) {
        String errorMessage = "Constructor " + cddConstructorName.getId() + "(";
        boolean first = true;
        for (TypeExpression arg : arguments) {
          if (first) first = false;
          else errorMessage += ", ";
          errorMessage += arg.getLabel();
        }
        errorMessage += ") is undefined";
        throw new Exception(errorMessage);
      } else { // exactly one constructor
        // Tries to determine if arguments match
        SignatureFacade constructor = createSignatureFacade(visibleConstructor.get(0));
        if (!constructor.isAConstructor()) {
          // Throw an exception
          String errorMessage = "Constructor " + cddConstructorName.getId() + "(";
          boolean first = true;
          for (TypeExpression t : arguments) {
            if (first) first = false;
            else errorMessage += ", ";
            errorMessage += t.getLabel();
          }
          errorMessage += ") is undefined";
          throw new Exception(errorMessage);
        }
        String potentialErrorMessage = constructor.isCompatibleWithMe(arguments, true);
        if (potentialErrorMessage.length() == 0) return constructor;
        else throw new Exception(potentialErrorMessage);
      }
    }

    throw new Exception("Not supported case");
  }