/*

Copyright: All contributers to the Umple Project

This file is made available subject to the open source license found at:
https://umple.org/license

The main Umple metamodel.

 */

namespace cruise.umple.compiler;
external interface Runnable {}

external Position{}
external Token{}
external RuleBasedParser{}

/*
 * Class UmpleModel is the central class describing the system being compiled.
 *
 * The model contains everything that was derived from an Umple file (.ump) when it was parsed such as
 * the classes, attributes, associations, state machines, methods, etc that were in it.
 *
 * Put another way, when an Umple file (.ump) is parsed an Umple model is populated with everything that was parsed from that file.
 *
 * Because of this it is absolutely critical to understand the model since it is basically the "root" of everything.
 */
class UmpleModel
{
  depend java.io.*;
  depend cruise.umple.analysis.*;
  depend cruise.umple.util.*;
  depend cruise.umple.compiler.exceptions.*;
  depend cruise.umple.parser.*;
  depend cruise.umple.parser.analysis.*;
  depend java.util.zip.*; // new
  isA Runnable;

  // The Umple file (.ump) that was used to populate the model.
  UmpleFile umpleFile;
  
  // Variables used for distributed code control
  Boolean distributeOn=true;
  Boolean distributeForced=false;
  Boolean distributed=false;
  
  // Variables used to advise not to bother trying to compile various language
  // because the code doesn't contain coherent or complete code. 
  // These are set to true when various @@@skip directives are found in comments
  Boolean skipcompile=false;
  Boolean skipjavacompile=false;
  Boolean skippythoncompile=false;
  Boolean skipcppcompile=false;
  Boolean skiprubycompile=false;
  Boolean skipphpcompile=false;
  
  Integer distributePattern=0;
  String distributeTechnology="RMI";
  defaultPackage = null;
  GenerateTarget[] generates;
  Boolean shouldGenerate = true;
  Glossary glossary = new Glossary();
  String defaultNamespace = null;
  String code = null;
  UmpleClass mainClass = null;
  Boolean debugMode = false;
  ParseResult lastResult = null;
  public static final String[] validLanguages = findValidLanguages();

  Map<String,String> generatedCode = new HashMap<String,String>();
  Map<String,Analyzer> analyzers = new HashMap<String,Analyzer>();
  
  // The core list of all requirement in this Model s found while parsing
  Map<String, Requirement> allRequirements = new HashMap<String, Requirement>();
  
  // The core list of all requirement implementation annotations found while parsing.
  * -> * ReqImplementation reqImplementations;

  // data for default class positioning
  internal Coordinate levelOffset = new Coordinate(200,100,0,0);
  internal Coordinate initialOffset = new Coordinate(50,30,0,0);
  internal Coordinate classSize = new Coordinate(0,0,109,45);
  internal int maxYLevels = 5;

  // Top level blocks code contained within a model.
  // extraCodes will be generated in a single file
  lazy CodeBlock[] extraCodes;

  // data for default association positioning
  internal Coordinate offsetFromEdge = new Coordinate(10,30,0,0);
  internal int reflexiveSegmentLength = 15;
  
  internal List<File> linkedFiles = new ArrayList<File>();

  // Whether tracer output should be generated if needed
  // These are set to false when tracer classes are created by generators
  Boolean generateConsole = true;
  Boolean generateFile = true;
  Boolean generateString = true;
  Boolean generateLog4j = true;
  
  // The Umple Enumerations contained within the model
  1 -> * UmpleEnumeration enums;

  // The Associations contained within the model.
  1 -> * Association;

  // The Umple Classes contained within the model.
  1 -> * UmpleClass;

  // The Umple Traits contained within the model.
  mixset Trait {
      1 -> * UmpleTrait;

  }

  // The Umple Templates contained within the model.
  1 -> * UmpleTemplate;

  // The State Machines contained within the model.
  mixset StateMachine {
      1 -> * StateMachine stateMachineDefinitions;

  }

  // The Umple interfaces contained within the model.
  1 -> * UmpleInterface;
  
  // Suboptions that might be added by the suboption command;
  lazy String[] availableSuboptions;
  before addGenerate(GenerateTarget) {
    for (String so : availableSuboptions) {
      aGenerate.addSuboption(so);
    }
  }

}



/*
 * An UmpleElement is one of the top-level items found in an Umple model
 * Currently it has one subclass, UmpleClassifier
 */
class UmpleElement
{
  depend cruise.umple.parser.Position;

  // The name of the Umple element.
  name;

  // The position(s) of the element in the source code, used in debugging
  //  may have multiple positions in the case of mixins
  1 -> 0..* Position positions;
  1 -> 0..* Position endPositions; // Kept aligned with positions

  // The modifier associated with the Umple element.
  modifier = null;

  Boolean hasMainMethod = false;

  String[] namespaces;

  NameSpace nameSpace = new NameSpace("",new Position("", 0, 0, 0));

  packageName = "";

  // The code associated with the Umple element.
  internal ExtraCode extraCode = new ExtraCode();

  // Specifies whether or not the Umple element is internal.
  Boolean isInternal = false;

  // Specifies the position of this Umple element (ex. The UmpleOnline diagram).
  Coordinate coordinates = new Coordinate(-1,-1,-1,-1);
  // Specifies the display color of this element
  String displayColor = "";

  before setPackageName { if (aPackageName == null) { return false; } }
  
  // Methods to distinguish the subclass types
  boolean isUmpleClass() {return false;}
  boolean isUmpleInterface() {return false;}
  mixset Trait {
      boolean isUmpleTrait() {return false;}

  }
}

/*
 * A method in an Umple class or interface
 * Umple Methods are coded by the programmer in the language(s) of their choice
 */
class Method
{
  depend cruise.umple.parser.Position;

  // Specifies whether or not the Method is abstract.
  Boolean isAbstract = false;

  // Specifies whether this is a constructor for the Umple class.
  Boolean isConstructor = false;
  
  // Specifies whether or not the method is queued.
  Boolean isQueued = false;

  // The modifier associated with the method.
  modifier;

  // The name of the method.
  name;

  // Throws exceptions
  String[] exceptions;

  lazy Position position;
  lazy Position codePosition;
  lazy Position endPosition;

  // The type of the method.
  type;

  // Specifies whether or not the method is implemented.
  Boolean isImplemented;

  //This supposed to show from where this method came.
  //fTrait means it comes from traits.
  //fAuto means it comes from auto generation mechanism.
  //fAutoAPI means it comes from auto generation mechanism to represent API methods at the model level.
  source {none,fTrait,fAuto,fAutoAPI}

  // The method parameters.
  1 -> 0..* MethodParameter;

  // The body of the method (such as the code within).
  1 -> 0..1 MethodBody;

  // The comments associated with the method (such as the Javadoc above it).
  1 -> * Comment;

  //The requirement ids implemented within the method.
  1 -> * ReqImplementation;
  
  // Specifies, for fAutoAPI methods, if the method was generated
  Boolean wasGenerated = false;
}




 /*
 * The contents of a method, such as the code within it.
 */
class MethodBody
{

  depend java.util.*;
  depend cruise.umple.parser.Position;

  // The code within the method body.
  extraCode = {codeblock.getCode() != null ? codeblock.getCode() : ""}
  CodeBlock codeblock;
  Map<String,Position> implementationPositions = new HashMap<String,Position>();
  
  
  //the method assertions
  1 -> * UmpleAssertion;
  0..1 -- * UmpleTestCase;
}

/*
* The assertion within the method or class.
*/

class UmpleAssertion {
	name;
	type;
	level;
	action;
	assertCode;
	int locOrder;
	boolean isTimed = false;
}

/*
* Test Case  at the  Class level .
*/

class UmpleTestCase {
	name;
	int locOrder;
	boolean isTimed = false;
	boolean isOverride = false;
	boolean isConcrete = false;
	String concreteLang = "";
	0..1 -- * UmpleAssertion;	
	0..1 -- * TestAction;
	0..1 -- * TestInit;	
	Map<Integer,String> bodyCode = new HashMap<Integer,String>();	
}



// test action statements
class TestAction{
  name;
  actionCode;
  type;
  int locOrder;

}


class TestParameter {
	String value;
	String type;
	String name;
}


class TestSequence {
 name;
 String[] tests = null;
 //0..1 -- 1 UmpleClass;
}


//initialization statements in test that holds
// identifier objectname (parameters);
class TestInit{
  identifier;
  objectName;
  code;
  
  0..1 -- * TestParameter;
  
}



/*
 * Represents a constant.
 */
class Constant
{
  // The name of the constant.
  name;

  // The type of the constant.
  type;

  // The modifier of the constant.
  modifier;

  // The value of the constant.
  value;

  //Issue 322 - by default set internal to false
  Boolean isInternal = false;
  
  // Commented out to prevent conflict with extending UmpleVariable
  // Previously, this extends would be overwritten, but Issue 1159 changes it to cause error 34
  // class UniqueIdentifier { }
}

/*
 * Represents a parameter in a method and its various forms.
 */
class MethodParameter
{
  isA UmpleVariable;

  // Specifies whether or not the method parameter is auto unique.
  Boolean isAutounique; // TODO: should default to false, but constructors would need updating

  // Specifies whether or not the method parameter is a list.
  Boolean isList = false;

  // Specifies whether or not the method parameter is derived.
  Boolean isDerived = false;

  // Specifies whether or not the method parameter is lazy.
  Boolean isLazy = false;
  
  // Specifies whether or not the method parameter is ivar.
  Boolean isIvar = false;
}

/*
 * ConstraintVariables encapsulate that data of one element in a ConstraintTree, making up the nodes of that tree.
 * For example: a<3
 *     has the structure:   ConstraintTree
 *                          ConstraintOperator(<)
 *                            /            \
 *                    ConstraintTree     ConstraintNumberLiteral(3)
 *               ConstraintAttribute(a)
 *     where all the "Constraint" classes inherit from ConstraintVariable
 */
class ConstraintVariable
{
  /*
   * ConstraintTrees are a redundant class that are necessary because of lone constraints, i.e. [true] has to be handled, and does not contain an operator
   * If lone constraints didn't exist then the ConstraintTree class could be condensed into ConstraintOperator. One nice religation of responsibilities is that ConstraintTrees take care of the ! and () symbols, leaving the ConstraintOperator class to be more pure
   */
  class ConstraintTree
  {
    depend cruise.umple.compiler.*;
    depend cruise.umple.parser.Token;
    depend java.util.*;

    ConstraintVariable root = null;
    ConstraintOperator requestor = null;
    TreeSet<String> names = new TreeSet<String>();

    boolean shouldDisplayBrackets = false;
    boolean displayNegation = false;
    boolean displayBrackets  = { shouldDisplayBrackets||(displayNegation&&numberOfElements>1) }

    int numberOfElements = 0;

    key { root }

    /*
     * TraceConstraint objects ensure that the attribute being traced will be treated as a parameter and not a member variable
     */
    class TraceConstraint
    {
      1 -> * UmpleVariable variables;
    }
    /*
     * The Preconditions are constraints on methods, restricting the method so that it does not process if the constraint is not satisfied.
     */
    class Precondition
    {
      * -> 1 Method ; // The method precondition belongs to
    }
    /*
     * The Preconditions are constraints on methods, throughing an exception if the constraint is not sastisfied after the method has computed.
     */
    class Postcondition
    {
      depend cruise.umple.parser.Position;
      * -> 1 Method ; // The method postcondition belongs to
      lazy Position position;
    }
  }

  /*
   * ConstraintOperators encapsulate the branching of the constraint tree, where the branches occur at the operators, for example
   * [a<3&&b!="loved"]
   * the basic structure will look like
   *                                        ConstraintOperator(&&)
   *                                      /                        \
   *              ConstraintOperator(<)                                ConstraintOperator(!=)
   *                  /            \                                      /                 \
   *     ConstraintAttribute(a) ConstraintNumberLiteral(3)   ConstraintAttribute(b)  ConstraintLiteral("loved")
   * With the extra complication that ConstraintTrees parent everything that are not ConstraintLiterals
   */
  class ConstraintOperator
  {
    value;
    1 -> 0..2 ConstraintVariable subConstraints;
    ConstraintVariable left = { numberOfSubConstraints()>0?getSubConstraint(0):null }
    ConstraintVariable right = { numberOfSubConstraints()>1?getSubConstraint(1):null }
    key { left, right, value }
  }

  /*
   * ConstraintLiterals encapulate raw data literals, such as strings, numbers and booleans, that do not have an model variable associated.
   * This will be a leaf in the constraint tree.
   */
  class ConstraintLiteral
  {
    value;
    /* Number literals are the special case of literals, where the value they contained is garanteed to be a number. */
    class ConstraintNumberLiteral
    {
    }
    key { value }
  }

  /*
   * This super class contains all subclasses that have elements with names
   */
  class ConstraintNamed
  {
    abstract;
    /*
     * The reason d'etre of this super class, it ensures that subclasses have getName methods
     */
    public abstract String getName();

    /*
     * ConstraintAttributes encapsulate the attribute for the constraint, this will be a leaf on the constraint tree
     */
    class ConstraintAttribute
    {
      Attribute attribute;
      index = -1;
      key { attribute }
    }

    /*
     * ConstraintAttributes encapsulate the association for the constraint, this will be a leaf on the constraint tree.
     */
    class ConstraintAssociation
    {
      AssociationVariable association;
      index = -1;
      numberOf = false;
      key { association }
    }

    /*
     * ConstraintMethodParameters are there for Preconditions and Postconditions, they encapsulate the MethodParameter that the constraint is refering to
     * This will be a leaf on the constraint tree.
     */
    class ConstraintMethodParameter
    {
      MethodParameter parameter;
      key { parameter }
    }

    /*
     * ConstraintUnassignedNames are names that were not recognized by the analysis, for example ConstraintMethodParameters are originally ConstraintUnassignedNames,
     * but are caught when they are added to the Precondition or Postcondition and a ConstraintMethodParameter is added instead of the ConstraintUnassignedName.
     */
    class ConstraintUnassignedName
    {
      value;
      key { value }
    }

    /*
     * ConstraintStates encapsulate the state data in a statemachine expression such as [sm is in state st], this is a leaf in the constraint tree/
     */

    class ConstraintState
    {
      mixset StateMachine {
      State state;
      key { state }
      }
    }

    /*
     * ConstraintStateMachines encapsulate the statemachine data in a statemachine expression such as [sm is in state st], this is a leaf in the constraint tree.
     */
    class ConstraintStateMachine
    {
      mixset StateMachine {
      StateMachine stateMachine;
      key { stateMachine }
      }
    }
    
    /*
     * ConstraintPort encapsulate the statemachine data in a port watch expression
     */
    class ConstraintPort
    {
      Port port;
      key { port }
    }
  }
}

/*
 * A block of code in an arbitrary language to be injected into generated code
 * Please update the method 'public CodeBlock(CodeBlock another)' if you add new attributes.
 */
class CodeBlock
{
  depend java.util.*;

  internal HashMap<String,String> codes = new HashMap<String,String>();
  public static String languageUsed = "";
  lazy String name;
}

/*
 * A block of code that can be injected into one or more methods, constructor, etc.
 */
class CodeInjection
{
  depend cruise.umple.parser.Position;
  depend cruise.umple.util.*;

  type;
  operation;
  operationSource = "generated";
  lazy String[] parameters;
  CodeBlock snippet;
  lazy constraintParameterName;
  * -> 1 UmpleClassifier;
  1 -> 0..1 ConstraintTree;
  lazy Position position;
  lazy Position codePosition;
  Boolean isInternal = false;
}

class ExtraCode
{
 internal CodeBlock[] code;
}

/*
 *
 * A key in a class is a set of attributes associations used to uniquely identify an object
 */
class Key
{
  Boolean isDefault = false;
  Boolean isInternal = false;
  String[] members;
}

/*
 * Represents an enumeration
 */
 class UmpleEnumeration
 {
   depend cruise.umple.parser.Position;
   
   name;
   String[] enumValues;
   1 -> 0..1 Position;
   1 -> * ReqImplementation;
 }

/*
 * Represents an Umple classifier: a Class or Interface
 */
class UmpleClassifier
{
  abstract;
  isA UmpleElement;
  
  depend cruise.umple.parser.Token;
  
  // The methods contained within the Umple Classifier.
  1 -> 0..* Method;

  * -> * Depend;
  
  // Specifies whether or not the Umple class or implemented classes are distributable with RMI technology.
  Boolean isDistributable = false;
  String distributeTechnology="RMI";
  UmpleModel sourceModel;

  // The constants contained within the Umple Classifier.
  1 -> 0..* Constant;
  1 -> 0..* ModelConstraint;
  * -> 0..1 Token extendsToken;
}

/*
 * Represents a interface.
 * Like a class, but can't have any concrete methods, attributes or associations.
 */
class UmpleInterface
{
  isA UmpleClassifier;

  * -> 0..* UmpleInterface extendsInterface;

  // The comments associated with the Umple Interface (such as the Javadoc above it).
  1 -> * Comment;

  //The requirement ids implemented within the Umple Interface.
  1 -> * ReqImplementation;
  
  0..1 -- * UmpleTestCase;

  before setPackageName { if (aPackageName == null) { return false; } }
  before addDepend { if (depends.contains(aDepend)) { return false; } }

  boolean isUmpleInterface() {return true;}
}

/*
 * An UmpleClass can contain attributes, associations, state machines and methods.
 * It can also have various other information such as a key (to identify uniqueness),
 * code to inject into generated code, and comments. It can be tagged with various
 * patterns, such as 'singleton', meaning that there can only be one instance,
 * and abstract, meaning it can't have any instances.
 */
class UmpleClass
{
  depend cruise.umple.util.*;

  isA UmpleClassifier;
  Boolean hasProxyPattern = false;
  Boolean needsDefaultInterface=false;
  Boolean isDistributed = false;
  Boolean isInternalSerializable = false;
  Boolean isDefaultInterfaceRemoteRMI=false;
  
  // dependency handling attributes
  
  Integer level = 0;
  Boolean isInitialized = false;
  


  // Specifies whether or not the Umple class is an abstract class.
  Boolean isAbstract = false;

  // Specifies whether or not the Umple class is a singleton.
  Boolean isSingleton = false;

  Association[] associations;
  
  // List of candidate methods that were not added to the class
  Method[] unimplementedMethods;

  Key key = new Key();

  // Specifies whether or not the Umple class is immutable.
  internal Boolean iAmImmutable = false;
  internal Boolean ancestorIsImmutable = false;

  1 -> * CodeInjection;

  // Enumerations that belong to the Umple Class
  1 -> * UmpleEnumeration enums;
  
  //The possible Preconditions related to the Umple Class
  1 -> 0..* Precondition preConds;

  //The possible Preconditions related to the Umple Class
  1 -> 0..* Postcondition postConds;
  
  //Umple Test Case at the class level
  0..1 -- 0..* UmpleTestCase;
  // class test sequence for testcases
  0..1 -- 0..* TestSequence;
  // class test initialization: inits at the top level
  0..1 -- 0..* TestInit;

  // The possible Constraints related to the Umple Class
  1 uClass -> 0..* ConstraintTree;

  // The Umple Class's super class (if there is one).
  * subclasses -- 0..1 UmpleClass extendsClass;
  
  //isStatic if the inner class is static
  // The inner classes contained within the Umple class.
  0..1 outerClass --  0..* UmpleClass innerClasses;
  boolean isStatic = false;

  //disable methods from being auto-generated by Umple.
  String[] disableAutogeneratedMethodList = new ArrayList<String>();

  * subClasses -- * UmpleTrait extendsTraits;

  * subClasses -- * UmpleTemplate extendsTemplates;

  * -> 0..* UmpleInterface parentInterface;

  1 -> 0..1 UniqueIdentifier;

  // The attributes contained within the Umple class.
  1 -- * Attribute;

  // The associations contained within the Umple class.
  0..1 -- * AssociationVariable;

  // The comments associated with the Umple Class (such as the Javadoc above it).
  1 -> * Comment;

  //The requirement ids implemented within the class.
  1 -> * ReqImplementation;

  //This is used to assign inheritance parameters.
  1 -> * GeneralTPApplied;

  before addDepend { if (depends.contains(aDepend)) { return false; } }

  //---before setImmutable { if (!canBeImmutable()) { return false; } }

  before addAssociationVariable { if (!immutabilityAssociationRulesSatisfied(aAssociationVariable, this.isImmutable())) { return false; } }

  before setExtendsClass { if (!enforceImmutabilityInheritanceRules(aExtendsClass)) { return false; } }

  mixset StateMachine {
  before addStateMachine { if (isImmutable()) { return false; } }
  }

  boolean isUmpleClass() {return true;}
}



/*
 * An UmpleTrait can contain attributes, associations, state machines and methods.
 * It can also have various other information such as a key (to identify uniqueness),
 * code to inject into generated code, and comments. It can be tagged with various
 * patterns.
 */

class UmpleTrait {
  depend cruise.umple.util.*;

  isA UmpleClassifier;

  // Specifies whether or not the Umple class is an abstract class.
  Boolean isAbstract = false;

  // Specifies whether or not the Umple trait is a singleton.
  Boolean isSingleton = false;

  Association[] associations;

  // List of candidate methods that were not added to the Trait
  Method[] unimplementedMethods;

  Key key = new Key();

  // Specifies whether or not the Umple trait is immutable.
  internal Boolean iAmImmutable = false;
  internal Boolean ancestorIsImmutable = false;

  1 -> * CodeInjection;

  //The possible Preconditions related to the Umple Trait
  1 -> 0..* Precondition preConds;

  //The possible Preconditions related to the Umple Trait
  1 -> 0..* Postcondition postConds;

  // The possible Constraints related to the Umple Trait
  1 uTrait -> 0..* ConstraintTree;

  // The Umple Trait's super Traits (if there are ones).
  * subTraits -- 0..* UmpleTrait extendsTraits;

  1 -> 0..1 UniqueIdentifier;

  // The attributes contained within the Umple trait.
  0..1 -- * Attribute;

  // The associations contained within the Umple trait.
  0..1 -- * AssociationVariable;

  // The comments associated with the Umple Trait (such as the Javadoc above it).
  1 -> * Comment;

  // The requirement associated with the Umple Trait (such as the Javadoc above it). 
  1 -> * ReqImplementation;

  //The template parameters which are specified when traits are defined.
  1 -> * GeneralTemplateParameter;

  //This is used to assign inheritance parameters.
  1 -> * GeneralTPApplied;

  //This is used to assign required interfaces
  1 -> * UmpleInterface requiredInterfaces;

  //trait test cases

  0..1 -- * UmpleTestCase;

  //--- before addDepend { if (depends.contains(aDepend)) { return false; } }

  //--- before setImmutable { if (!canBeImmutable()) { return false; } }

  //--- before addAssociationVariable { if (!immutabilityAssociationRulesSatisfied(aAssociationVariable, this.isImmutable())) { return false; } }

  //--- before setExtendsTrait { if (!enforceImmutabilityInheritanceRules(aExtendsClass)) { return false; } }

  mixset StateMachine {
  before addStateMachine { if (isImmutable()) { return false; } }
  }

  boolean isUmpleTrait() {return true;}
}

//This class is used to specify parameters for traits.
//TODO : when can also apply this to support formal template concepts for classes.
class GeneralTemplateParameter {
	name;
	type;
	String[] interfacesAndClass;
	defaultValue = "";

}

//This class is used to assign parameters in classes and traits.
class GeneralTPApplied {
  depend cruise.umple.parser.Position;

	inheritanceName;
	String[] parameters;
	1 -> 0..1 Position positions;
	1 -> * MethodTemplateSignature;
  mixset StateMachine {
	1 -> * StateMachineTemplateSignature;
	1 -> * StateMachineModifier;
  }
}

class MethodTemplateSignature{
	modifier;
	1 -> 1 Method;
	alias;
}

mixset StateMachine {
class StateMachineTemplateSignature{
	modifier;
	srcStateMachine;
	desStateMachine;
	String[] srcStates;
	String[] desStates;
	0..1 -> 0..1 MethodTemplateSignature;
	alias;
}


class StateMachineModifier{
  modifier;
  srcStateMachine;
  alias;
}

//This is used to remove and rename a state.
class StateModifier{
  isA StateMachineModifier;
  String[] srcStates;
}

//This is used to remove an event or a transition.
class EventModifier{
  isA StateModifier;
  0..1 -> 0..1 Method;
  0..1 -> 0..1 Guard;
//  Token guardToken = null;
}

//This is used to extend a state with a state machine.
class ExtendStateByStateMachine{
  isA StateMachineModifier;
  String[] desStates;
}
}
/*
 * A depend relationship indicates a package on which this class depends
 */
class Depend
{
  name;
  Boolean isInternal = false;

  key { name }
}

/*
 * A combination of Class and Association (as defined in UML)
 * An AssociationClass is a full-fledged class, but at the same time
 * It associates two other classes that would otherwise have a many-many
 * relationship. Instances of the AssociationClass represent data
 * held by the links between those two classes.
 */
class AssociationClass
{
  isA UmpleClass;
  1 -> 0..2 Association associatedTo;
}

/*
 * Superclass for tracking member variables in all target languages
 * TODO: Code smell because we have both an association variable and also an association
 * This class should go and instead AssociationEnd should be the member variable
 */
class UmpleVariable
{
  // The name of the Umple variable.
  name;

  // The type of the Umple variable.
  type;

  // The modifier associated with the Umple variable.
  modifier; // potential enum, 'settable'

  // The value of the Umple variable.
  value;

  before setName { if (aName == null) { throw new RuntimeException("Name must be set, cannot be null"); } }
  before getModifier { if (modifier == null) { return "settable"; } }
	after constructor {
  	if (type==""){
  		 type= "String";
  	}
  }

  class UniqueIdentifier { }
}

/*
 * Represents an attribute.
 * An attribute is more abstract than an instance variable / property in that
 * it can be derived, and have various other modifiers such as being
 * initialized, lazy (does not appear in constructor and must be initialized
 * after construction), etc.
 */
class Attribute
{
  depend cruise.umple.parser.Position;

  isA UmpleVariable;

  // Specifies whether or not the method parameter is auto unique.
  // TODO: should default to false, but constructors would need updating
  Boolean isAutounique;

  // Specifies whether or not the attribute is unique.
  Boolean isUnique = false;

  // Specifies whether or not the method parameter is a list.
  Boolean isList = false;

  // Specifies whether or not the method parameter is derived.
  Boolean isDerived = false;

  // Specifies whether or not the method parameter is internalTransient.
  Boolean isInternalTransient = false;

  CodeBlock codeblock = new CodeBlock();

  after constructor { codeblock.setCode(normalizeValue(aType,aValue)); }
  before setType { codeblock.setCode(normalizeValue(aType,getValue())); }
  after setType { setValue(getValue()); }
  mixset Trace {
    before delete { 
      if (traceRecords == null) {
        traceRecords = new ArrayList<TraceRecord>();
      }
    }
  }

  // Specifies whether or not the method parameter is lazy.
  Boolean isLazy = false;
  Boolean isRefinement = false;
  
  // Specifies whether or not the method parameter is ivar.
  Boolean isIvar = false;

  //This supposed to show from where this method came.
  //fTrait means it comes from traits.
  //
  source {none,fTrait}
  // The comments associated with the attribute (such as the Javadoc above it).
  1 -> * Comment;

 //The requirement ids implemented within the attribute.
  1 -> * ReqImplementation;

  // In case this attribute needs to have error handling preformed
  1 -> 0..1 Position;
  1 -> 0..1 Position endPosition;
}

/*
 * Represents an association, typically between two Umple classes (1-1, 1-*, *-1, etc).
 * An association in UML/Umple represents a relationship that exists at run time
 * where instances of one class reference the other, and (if bidirectional) instance
 * of the other class reference the first cass.
 * The number of references is governed by the Multiplicity at each AssociationEnd
 */
class Association
{
  depend cruise.umple.parser.Position;
  
  // The name of the association.
  name = null;
  Boolean isLeftNavigable;
  Boolean isRightNavigable;
  Boolean isLeftComposition;
  Boolean isRightComposition;
  Coordinate[] positions;
  0..1 -- 2 AssociationEnd ends;
  Position tokenPosition = null;
  Position tokenEndPosition = null;
  internal Boolean immutable = false;
  Boolean named = { name != null && !"".equals(name) }

  // code for specialized associations
  // the 0..1 parent -- * specializedAssociations is the code to handle the following:
  // parent denotes which association this one is tightening
  // specializedAssociations is a list of associations that have specialized this "parent" one
  0..1 specializedFrom -- * Association specializedAssociations;
  Boolean isSpecialized = false;
  Boolean isSpecialization = false;
  // name of the class this association shares with its parent
  commonClassName = "";

  //The source of association
  //None: origial
  //fTrait: from traits
  source {none,fTrait}

  before getName { if (!isNamed()) { return this.deriveName(); } }
  after constructor { this.setLeftAndRight(); }
  // Issue 2098: enable implementsReq to be placed before a top-level association block
  1 -> * ReqImplementation;
}

/*
 * An association end represents one logical end of an association
 *
 * See also AssociationVariable
 * TODO: Code smell referenceToClassName is a duplication, can access via the association
 * Create a derived attribute otherend (the other AssociationEnd)
 */
class AssociationEnd
{
  roleName;
  className;
  modifier; // potential enum 'internal'
  referenceToClassName;
  Multiplicity multiplicity;
  Boolean isDefaultRoleName = false;
  String priority = "";

  // relevant to specializations
  String superClassName = "";
  Boolean needsCommonCode = false;
  Boolean needsSuperCode = false;
  Boolean mulChangedToOne = false;
  Boolean mulChangedToN = false;
  Boolean reqSetCode = false;

  key { multiplicity, roleName, className, modifier, referenceToClassName }
  //modifier { Settable, Immutable, Internal, Defaulted, Constant }

  before getRoleName { if (roleName == null) { return ""; } }
  before getClassName { if (className == null) { return ""; } }
  before getModifier { if (modifier == null || "".equals(modifier)) { return "internal"; } }
  before getReferenceToClassName { if (referenceToClassName == null) { return ""; } }
}

/*
 * An association variable represents one of the variables used to represent
 * an association. In a two-directional association (navigable) there would
 * be one of these in each associated class.
 *
 * See also AssociationEnd
 *
 * TODO: Code smell. Should be replaced by the 'otherEnd' of the AssociationEnd
 */
class AssociationVariable
{
  isA UmpleVariable;
  Multiplicity multiplicity;
  immutable Boolean isNavigable;
  Boolean isComposition = false;
  String priority = "";

  0..1 self relatedAssociation;

  // specialized from this association variable
  AssociationVariable specializedFromVariable = null;

  // code relevant to specialization of associations
  Boolean isSpecialized = false;		// is it ever specialized?
  Boolean isSpecialization = false;		// is it a specialization of another?
  commonClassName = "";
  superClassName = "";
  int relevantEnd = 0;					// 0 to ensure that everything doesn't break
  Boolean needsSuperCode = false;
  Boolean needsCommonCode = false;
  Boolean mulChangedToOne = false;
  String scName = "";
  Boolean mulChangedToN = false;
  Boolean reqSetCode = false;

  // The comments associated with the association (such as the Javadoc above it).
  1 -> * Comment;

  //The requirement ids implemented within the association variable.
  1 -> * ReqImplementation;

  before setUmpleClass { if ((aUmpleClass != null) && !aUmpleClass.immutabilityAssociationRulesSatisfied(this, aUmpleClass.isImmutable())) { return false; } }

  before setRelatedAssociation { if(!canBeRelatedAssociation(aNewRelatedAssociation)) { return false; }}
}

/*
 * A multplicity constrains the number of linked objects at one end of an
 * association
 *
 * TODO: extract derived attributes from Umple_Code.ump (getLowerBound etc.)
 */
class Multiplicity
{
  depend cruise.umple.util.*;

  lazy bound; // used when minimum=maximum;
  lazy minimum;
  lazy maximum;

  parserable = { getBound() != null ? getBound() : ( (getMinimum() == null ||  getMinimum().equals("0")) && (getMaximum() == null || getMaximum().equals("*")) ? "*" : ""+ getMinimum() + ".." + getMaximum()) }

  key { bound, minimum, maximum }

}

// TODO: Code smell: This duplicates the structure of the class from UmpleClass
// This is a problem for model-to-model transformations
// Should be abolished
class GeneratedElement
{
  depend java.util.*;
}

/*
 * Represents a class that is generated from an Umple class, such as a Java or Cpp class.
 */
class GeneratedClass
{
  isA GeneratedElement;

  // Generated classes come from an Umple model (which comes from an Umple file), hence many generated classes to one model.
  * -> 1 UmpleModel model;

  // Generated classes are translated from an Umple class, hence the relation.
  0..1 -> 1 UmpleClass uClass;

  // Generated classes may have a parent class/super class.
  0..1 -> 0..1 GeneratedClass parentClass;
}

//class GeneratedInterface
//{
//  isA GeneratedElement;
//  //code = null;
//  * -> 1 UmpleModel model;
//  0..1 -> 1 UmpleInterface uInterface;
//}

/*
 * A point in cartesian coordinates, used in representing the layout of a
 * diagram in Umple
 */
class Point
{
  Integer x;
  Integer y;

  key { x, y }
}

/*
 * A Coordinate is used in  the layout of classes
 * It represents the shape of a class box in a diagram
 */
class Coordinate
{
  Integer x;
  Integer y;
  Integer width;
  Integer height;
  status {Explicit, Undefined, Defaulted}

  after constructor { updateStatus(); }
  after setX { if(wasSet) updateStatus(); }
  after setY { if(wasSet) updateStatus(); }
  after setWidth { if(wasSet) updateStatus(); }
  after setHeight { if(wasSet) updateStatus(); }

  key { x, y, width, height }
}

/*
 * Represents a comment, such as those found around classes, methods, attributes and associations.
 */
class Comment
{
  depend java.util.*;

  // The text associated with the comment.
  text;
  Boolean annotation = false;
}


/*
 * Represents a requirement, such as those found around
 * classes, methods, attributes, associations, stateMachines, states, etc.
 * If multiple occurrences of a requirement are found, their statements are concatenated
 * and a single instance is created.
 * If the language of two occurrences differs (and neither is blank) the the latter occurrences
 * is ignored with warning 401
 * All instances of this class are tracked in the instance of Model
 * with the map allRequirements, whose key is the identifier
 */
class Requirement{
  depend java.util.*;
  depend cruise.umple.parser.Token;

  // A unique identifier for this requirement
  // Alphanumeric, with -, . and _ allowed
  // TODO: add an Umple 'key' statement for this.
  identifier;
  
  // The content of the requirement, expressed in the language
  statement;

  // Structured user story elements
  who;
  when;
  what;
  why;
  
  // The requirements language used to express this requirement
  // can be blank, then 'text' is assumed
  // Other languages can be added e.g. GRL = Goal Requirement Language
  language;
  
  // List of tokens where the requirement was found
  // Used when reporting errors regarding missing implementations
  // and when reporting where a requirement is located in the code
  * -> * Token reqToken;

  // Ordered structured use case steps such as userStep/systemResponse
  1 -- * UseCaseStep;

  // Quality classes defined within this requirement
  // format: `req <req_name> [quality|Quality] {(<quality_name>{...})*}`
    1 -- * QualityClass;
}

class QualityClass
{
  name;
  // Reserved for {}; currently expected empty and will do nothing on it. If it is not empty, warning will occur
  content;
}

class UseCaseStep
{
  enum UseCaseStepType
  {
    userStep,
    systemResponse
  }

  id;
  UseCaseStepType stepType;
  content;
}

/*
 * Represents an implementation of a requirement
 * Stored to allow for analysis of matching requirement
 * and reporting on what features implement what requirement
 * all instances of this class are tracked in the instance of the model
 * with the association allReqImplementations
 * Note that there can be multiple instances of this class for each identifier
 * because, for example, multiple methods may be needed to implement a given requirement
 */
class ReqImplementation {
  depend cruise.umple.parser.Token;
  depend java.util.*;

  // unique identifier that should match the identifier of a Requirement
  identifier;

  // Because the QualityClass maybe not accessible in the parse stage, so only store its name first
  lazy qualityClassName;

  // bound during post-parse if qualityClassName matches a QualityClass in the Requirement
  * -> 0..1 QualityClass;


  // After analysis of the code, this will identify the requirement if there is one
  // If there are zero requirements it would indicate a mismatch (warning 402)
  // A requirement can have many implementing features.
  * -- 0..1 Requirement;

  // The location in the code where the implementation was found, so we can
  // report warning 402 if we find no matching requirement
  // and so we can output a requirements document that enables the reader to find each implementation
  * -> 1 Token reqToken;
  
  // the class, attribute, state machine, state, association, mixset etc. that the
  // implementation corresponds to, e.g. 'class Person'
  lazy implementingFeature;
}

class UmpleTemplate {
  depend cruise.umple.util.*;
  isA UmpleClass;
}

/*
 * Represents the generation target, such as what the generated output language will be.
 */
class GenerateTarget
{
  // The target language, such as Java, Cpp, Php or Ruby.
  language;

  path;

  Boolean override = false;
  Boolean overrideAll = false;
  lazy String[] suboptions;

  before getPath{if(path == null) path = ""; }
  key{language}
  public Boolean tarHasSubOption(String subOption){
  return suboptions.contains(subOption);
  }
}

//added for issue 1315 warning 31
class NameSpace
{
  depend cruise.umple.parser.Position;

  immutable value;
  immutable Position position;
  Integer timesUsed = 0;
  before setTimesUsed{if(aTimesUsed <0) return false; }
}

// UmpleObject is used to initialize classes 
class UmpleObject {
  type;
  name;
  0..1 -- * ObjectElement;
  //* -- 0..1 UmpleClass;  
}

// object element is any element with type value and name, such as attribute or Umple element.
class ObjectElement {
  type;
  name;
  value;  
}

class Port {

  depend cruise.umple.parser.Position;
	
	direction { IN{} OUT{} BOTH{} }
	type { END{} RELAY{} SERVICE{} CUSTOM{} }
	name;
	modifier;	
	boolean conjugated;
	int multiplicity;
	boolean replicated;
	
	String signalType;
		
	before setUmpleClass { if (aUmpleClass != null && aUmpleClass.isImmutable()) { return false; } }
	
	1 -> 0..1 Position;
  1 -> 0..1 Position endPosition;
}


use UmpleVersion.ump;
use UmpleDiagram.ump;
//use stateMachine/StateMachine.ump;
use Umple_Code.ump;
use UmpleEnumeration_Code.ump;
mixset Mixset{
  use mixset/Mixset.ump;
}
mixset FeatureModel {
  use feature/FeatureModel.ump;
}
