package com.openMap1.mapper.structures;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EReference;
import com.openMap1.mapper.util.ModelUtil;
/**
* Class recording an actual association that is mappable,
* noting the actual classes at both ends, which have class mappings and which may be
* different from the classes the association is inherited from
*/
public class MappableAssociation {
/**
* if the EReference which is the basis of this association has no EOpposite,
* then the role name which corresponds to no EReference (i.e to navigate to the class
* which, according to the Ecore model, you cannot navigate to) is this role name.
* This is always end 2 of the association; the role which points to end 1 is navigable,
* The association name is the same as the navigable role name
*/
public static String NON_NAVIGABLE_ROLE_NAME = "";
private EClass thisEndClass;
/**
* the class at one end of the association
* that was selected in the mapped class model view when the action
* to create the association mapping was made
*/
public EClass thisEndClass() {return thisEndClass;}
private String thisEndSubset;
/**
* @return the mapped subset of the selected class in the class model view
*/
public String thisEndSubset() {return thisEndSubset;}
private EClass otherEndClass;
/**
* the class at one end of the association
* - the end whose class was not the one selected in the mapped class model view when the action
* to create the association mapping was made
*/
public EClass otherEndClass() {return otherEndClass;}
private String otherEndSubset;
/**
* @return the mapped subset of class which is not the selected class in the class model view
*/
public String otherEndSubset() {return otherEndSubset;}
private EReference thisEndReference;
/**
* the eReference from the class at one end of the association
* - the class that was selected in the mapped class model view when the action
* to create the association mapping was made. This is the EReference to
* get to the class at the other end, and is never null
*/
public EReference thisEndReference() {return thisEndReference;}
/**
* the eReference from the class at one end of the association
* - the end whose class was not the one selected in the mapped class model view when the action
* to create the association mapping was made
*/
public EReference otherEndReference() {return thisEndReference.getEOpposite();}
private boolean makeRequiredForThisEnd;
public boolean requiredForEnd(int end)
{
boolean required = false;
if (end == thisEndIndex()) required = makeRequiredForThisEnd;
return required;
}
//------------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------------
public MappableAssociation(EClass thisEndClass, String thisEndSubset,
EClass otherEndClass,String otherEndSubset, EReference thisEndReference,
boolean makeRequiredForThisEnd)
{
this.thisEndClass = thisEndClass;
this.thisEndSubset = thisEndSubset;
this.otherEndClass = otherEndClass;
this.otherEndSubset= otherEndSubset;
this.thisEndReference = thisEndReference;
this.makeRequiredForThisEnd = makeRequiredForThisEnd;
}
/**
* Index 1 or 2 for 'this' end of the association -
* the end of the class selected in the class model view
*/
private int thisEndIndex()
{
/* If there is no EReference back from the other end, the other end is end 1
* so this end is end 2 */
int thisEnd = 2;
if (otherEndReference() != null)
{
// end 1 is the end whose role name is lexically first
if (thisEndReference().getName().compareTo(otherEndReference().getName()) < 0) thisEnd = 1;
// compareTo: The result is a negative integer if this String object lexicographically precedes the argument string
}
return thisEnd;
}
/**
* Index 1 or 2 for the 'other' end of the association - not the end of the class selected in the class model view
*/
private int otherEndIndex() {return (3 - thisEndIndex());}
/**
* @return the name of the association, made by the rules:
* (1) if there is only one EReference, with no opposite, the name is the role name of the EReference
* (2) if there are two role names <role1> and <role2>, the association name is '<role1>|<role2>', except that
* (3) (legacy) if the role names differ only by a final '_1' and '_2',
* the association name is the first role name without the final '_1'
*
*/
public String associationName()
{
if (otherEndReference() != null)
{
String n1 = endRef(1).getName();
String n2 = endRef(2).getName();
return ModelUtil.assocName(n1, n2);
}
// if there is no opposite reference, the association name is the one role name
return thisEndReference().getName();
}
/**
* the EReference from one end (= 1 or 2) to the other
* @param end
* @return the EReference - may be null for a non-navigable association
*/
public EReference endRef(int end)
{
EReference ref = null;
if ((end < 1)|(end > 2)) System.out.println("Invalid end for EReference: " + end);
else if (end == thisEndIndex()) ref = thisEndReference;
else if (end == otherEndIndex()) ref = otherEndReference();
return ref;
}
/**
* @param end
* @return the role name for a role pointing _from_ a defined end of the association
*/
public String roleName(int end)
{
String name = "";
if ((end < 1)|(end > 2)) System.out.println("Invalid end for role name: " + end);
else if (end == thisEndIndex()) name = thisEndReference.getName();
// the role pointing from the other end to this end might be non-navigable
else if (end == otherEndIndex())
{
name = NON_NAVIGABLE_ROLE_NAME;
if (otherEndReference() != null) name = otherEndReference().getName();
}
return name;
}
/**
* the EClass pointed _to_ at one end of the association
* (Note the EReference at end 1 belongs to the EClass at end 1,
* but points to the EClass at end 2)
* @param end = 1 or 2
* @return the mapped subset of the EClass pointed to by that EReference
*/
public String getSubset(int end)
{
String subset = "";
if ((end < 1)|(end > 2)) System.out.println("Invalid end for subset name: " + end);
// note the reversal of this and other ends, in the class pointed at
else if (end == thisEndIndex()) subset = otherEndSubset;
else if (end == otherEndIndex()) subset = thisEndSubset;
return subset;
}
/**
* the EClass pointed _to_ at one end of the association
* (Note the EReference at end 1 belongs to the EClass at end 1,
* but points to the EClass at end 2)
* @param end = 1 or 2
* @return the EClass pointed to by that EReference
*/
public EClass endClass(int end)
{
EClass c = null;
if ((end < 1)|(end > 2)) System.out.println("Invalid end for EClass: " + end);
// note the reversal of this and other ends, in the class pointed at
else if (end == thisEndIndex()) c = otherEndClass;
else if (end == otherEndIndex()) c = thisEndClass;
return c;
}
/**
* @return a label for the association to be mapped - which is
* of the form [thisClass]thisRole[otherEndClass].
* ThisClass is the class selected in the mapped class model view.
*/
public String associationMenuLabel()
{
String thisEnd = thisEndClass.getName();
if (!thisEndSubset.equals("")) thisEnd = thisEnd + "(" + thisEndSubset + ")";
String otherEnd = otherEndClass.getName();
if (!otherEndSubset.equals("")) otherEnd = otherEnd + "(" + otherEndSubset + ")";
return ("[" + thisEnd + "]"
+ thisEndReference.getName()
+ "[" + otherEnd + "]");
}
}