mirror of https://github.com/eitch/first-wave.git
mim.meta initial commit.
This commit is contained in:
parent
1a965a4d2f
commit
8fa4d79ad7
|
@ -0,0 +1,4 @@
|
|||
/.classpath
|
||||
/.project
|
||||
/target
|
||||
/.settings
|
|
@ -0,0 +1,16 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>ch.bitwave</groupId>
|
||||
<artifactId>maven.platform.parent</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>mim.meta</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>mentor meta model</name>
|
||||
<description>contains the meta model of the mentor</description>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,155 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* An association describes a set of tuples whose values refer to typed
|
||||
* instances. An instance of an association is called a link. A link is a tuple
|
||||
* with one value for each end of the association, where each value is an
|
||||
* instance of the type of the end.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* An association specifies a semantic relationship that can occur between typed
|
||||
* instances. It has at least two ends represented by properties, each of which
|
||||
* is connected to the type of the end. More than one end of an association may
|
||||
* have the same type.
|
||||
* </p>
|
||||
* <p>
|
||||
* An end property of an association that is owned by an end class or that is a
|
||||
* navigable owned end of the association indicates that the association is
|
||||
* navigable from the opposite ends, otherwise the association is not navigable
|
||||
* from the opposite ends.
|
||||
* </p>
|
||||
*/
|
||||
public class Association extends Classifier implements Relationship {
|
||||
|
||||
private List<Property> ownedEnds;
|
||||
private List<Property> memberEnds;
|
||||
|
||||
public Association() {
|
||||
this.ownedEnds = new ArrayList<Property>();
|
||||
this.memberEnds = new ArrayList<Property>();
|
||||
}
|
||||
|
||||
public Namespace getOwningNamespace() {
|
||||
return getOwnerAs(Namespace.class);
|
||||
}
|
||||
|
||||
public void setOwningNamespace(final Namespace owningNamespace) {
|
||||
this.setOwner(owningNamespace);
|
||||
}
|
||||
|
||||
/**
|
||||
* The ends that are owned by the association itself. This is an ordered
|
||||
* association. Subsets {@link Association#getMemberEnds()},
|
||||
* {@link Classifier#getFeatures()} and {@link Namespace#getOwnedMembers()}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<Property> getOwnedEnds() {
|
||||
return this.ownedEnds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Each end represents participation of instances of the classifier
|
||||
* connected to the end in links of the association. This is an ordered
|
||||
* association and a subset of {@link #getMembers()}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<Property> getMemberEnds() {
|
||||
return this.memberEnds;
|
||||
}
|
||||
|
||||
/**
|
||||
* References the classifiers that are used as types of the ends of the
|
||||
* association.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<MimType> getEndTypes() {
|
||||
List<MimType> result = new ArrayList<MimType>();
|
||||
for (Property element : getMemberEnds()) {
|
||||
result.add(element.getType());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MimElement> getRelatedElements() {
|
||||
ArrayList<MimElement> result = new ArrayList<MimElement>(this.ownedEnds);
|
||||
result.addAll(this.memberEnds);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* The navigable ends that are owned by the association itself. Subsets
|
||||
* {@link #getOwnedEnds()}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<Property> getNavigableOwnedEnds() {
|
||||
// TODO: filter by navigability.
|
||||
return this.ownedEnds;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void contributeFeatures(final List<Feature> list) {
|
||||
super.contributeFeatures(list);
|
||||
list.addAll(this.ownedEnds);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void contributeOwnedMembers(final List<NamedElement> list) {
|
||||
list.addAll(this.ownedEnds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOwnedMember(final NamedElement member) {
|
||||
Property prop = assertProperty(member);
|
||||
prop.setOwner(this);
|
||||
prop.setRelationship(this);
|
||||
this.memberEnds.add(prop);
|
||||
this.ownedEnds.add(prop);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeOwnedMember(final NamedElement member) {
|
||||
Property prop = assertProperty(member);
|
||||
if (prop.getOwner() == this) {
|
||||
prop.setOwner(null);
|
||||
}
|
||||
if (prop.getRelationship() == this) {
|
||||
prop.setRelationship(null);
|
||||
}
|
||||
this.memberEnds.remove(prop);
|
||||
this.ownedEnds.remove(prop);
|
||||
}
|
||||
|
||||
protected Property assertProperty(final NamedElement member) {
|
||||
if (!(member instanceof Property)) {
|
||||
throw new RuntimeException(
|
||||
String.format(
|
||||
"An association can only own elements of type Property, but the given element is of type %s.",
|
||||
member.getClass().getSimpleName()));
|
||||
}
|
||||
Property prop = (Property) member;
|
||||
return prop;
|
||||
}
|
||||
|
||||
public void addMember(final NamedElement member) {
|
||||
if (!(member instanceof Property)) {
|
||||
throw new RuntimeException(
|
||||
String.format(
|
||||
"An association can only have members of type Property, but the given element is of type %s.",
|
||||
member.getClass().getSimpleName()));
|
||||
}
|
||||
Property prop = (Property) member;
|
||||
prop.setRelationship(this);
|
||||
this.memberEnds.add(prop);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,275 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* A classifier is a classification of instances — it describes a set of
|
||||
* instances that have features in common.
|
||||
*/
|
||||
public abstract class Classifier extends Namespace {
|
||||
private List<GeneralizationEnd> generals;
|
||||
private List<GeneralizationEnd> specifics;
|
||||
private boolean abstractClassifier;
|
||||
private List<Feature> nonOwnedFeatures;
|
||||
|
||||
public Classifier() {
|
||||
super();
|
||||
this.nonOwnedFeatures = new ArrayList<Feature>();
|
||||
this.generals = new ArrayList<GeneralizationEnd>();
|
||||
this.specifics = new ArrayList<GeneralizationEnd>();
|
||||
}
|
||||
|
||||
public boolean isAbstract() {
|
||||
return this.abstractClassifier;
|
||||
}
|
||||
|
||||
public void setAbstract(final boolean value) {
|
||||
this.abstractClassifier = value;
|
||||
}
|
||||
|
||||
public void addGeneral(final GeneralizationEnd genEnd) {
|
||||
this.generals.add(genEnd);
|
||||
}
|
||||
|
||||
public void removeGeneral(final GeneralizationEnd genEnd) {
|
||||
this.generals.remove(genEnd);
|
||||
}
|
||||
|
||||
public void addSpecific(final GeneralizationEnd genEnd) {
|
||||
this.specifics.add(genEnd);
|
||||
}
|
||||
|
||||
public void removeSpecific(final GeneralizationEnd genEnd) {
|
||||
this.specifics.remove(genEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of features directly introduced by this classifier.
|
||||
*
|
||||
* @return the list of features.
|
||||
*/
|
||||
public List<Feature> getFeatures() {
|
||||
List<Feature> result = new ArrayList<Feature>();
|
||||
contributeFeatures(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void contributeFeatures(final List<Feature> list) {
|
||||
list.addAll(this.nonOwnedFeatures);
|
||||
}
|
||||
|
||||
/**
|
||||
* The query allFeatures() gives all of the features in the namespace of the
|
||||
* classifier. In general, through mechanisms such as inheritance, this will
|
||||
* be a larger set than feature.
|
||||
*
|
||||
* @return the complete list of features attributed to this classifier.
|
||||
*/
|
||||
public List<Feature> getAllFeatures() {
|
||||
List<Feature> result = getFeatures();
|
||||
for (Classifier parent : getAllParents()) {
|
||||
parent.contributeFeatures(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Generalization> getGeneralizations() {
|
||||
List<Generalization> result = new ArrayList<Generalization>();
|
||||
for (GeneralizationEnd general : this.generals) {
|
||||
result.add(general.getGeneralization());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Generalization> getSpecializations() {
|
||||
List<Generalization> result = new ArrayList<Generalization>();
|
||||
for (GeneralizationEnd general : this.specifics) {
|
||||
result.add(general.getGeneralization());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the more general classifiers in the generalization hierarchy
|
||||
* for this Classifier.
|
||||
*
|
||||
* @return the list of generals.
|
||||
*/
|
||||
public List<Classifier> getGenerals() {
|
||||
List<Classifier> result = new ArrayList<Classifier>();
|
||||
for (GeneralizationEnd genend : this.generals) {
|
||||
result.add(genend.getGeneralization().getGeneral());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the more general classifiers in the generalization hierarchy
|
||||
* for this Classifier.
|
||||
*
|
||||
* @return the list of generals.
|
||||
*/
|
||||
public List<Classifier> getSpecifics() {
|
||||
List<Classifier> result = new ArrayList<Classifier>();
|
||||
for (GeneralizationEnd genend : this.specifics) {
|
||||
result.add(genend.getGeneralization().getSpecific());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all of the immediate ancestors of this Classifier. Synonymous for
|
||||
* {@link #getGenerals()}.
|
||||
*
|
||||
* @return the list of direct parents.
|
||||
*/
|
||||
public List<Classifier> getParents() {
|
||||
return getGenerals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all of the direct and indirect ancestors of this Classifier.
|
||||
*
|
||||
* @return the list of all parents, including indirect ones.
|
||||
*/
|
||||
public List<Classifier> getAllParents() {
|
||||
List<Classifier> result = new ArrayList<Classifier>();
|
||||
this.contributeParents(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void contributeParents(final List<Classifier> list) {
|
||||
list.add(this);
|
||||
for (Classifier parent : getParents()) {
|
||||
parent.contributeParents(list);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void contributeOwnedElements(final List<MimElement> result) {
|
||||
super.contributeOwnedElements(result);
|
||||
result.addAll(getFeatures());
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies all elements inherited by this classifier from the general
|
||||
* classifiers. Subsets the namespace members.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<NamedElement> getInheritedMembers() {
|
||||
List<NamedElement> result = new ArrayList<NamedElement>();
|
||||
List<Classifier> generals = getGenerals();
|
||||
for (Classifier general : generals) {
|
||||
result.addAll(general.getAllFeatures());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isStereotype(final Stereotype stereotype) {
|
||||
List<Property> properties = getOwnedMembersOfType(Property.class);
|
||||
for (Property property : properties) {
|
||||
Relationship rel = property.getRelationship();
|
||||
if (rel instanceof Extension) {
|
||||
Extension ext = (Extension) rel;
|
||||
if (stereotype == ext.getMetaClass()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> List<T> getFeaturesOfType(final java.lang.Class<T> featureType) {
|
||||
List<T> result = new ArrayList<T>();
|
||||
for (Feature feature : getFeatures()) {
|
||||
if (featureType.isAssignableFrom(feature.getClass())) {
|
||||
result.add((T) feature);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void addNonOwnedFeature(@Nonnull final Feature feature) {
|
||||
this.nonOwnedFeatures.add(feature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this classifier is a specialization of the given
|
||||
* classifier.
|
||||
*
|
||||
* @param general
|
||||
* the classifier to test as a general of this classifier.
|
||||
* @return true if general is an ancestor of this classifier.
|
||||
*/
|
||||
public boolean isSpecializationOf(final Classifier general) {
|
||||
for (GeneralizationEnd genend : this.generals) {
|
||||
if (genend.getGeneralization().getGeneral() == general) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this classifier is a generalization of the given
|
||||
* classifier.
|
||||
*
|
||||
* @param specific
|
||||
* the classifier to test as a specific of this classifier.
|
||||
* @return true if general derives from this classifier.
|
||||
*/
|
||||
public boolean isGeneralizationOf(final Classifier specific) {
|
||||
for (GeneralizationEnd genend : this.specifics) {
|
||||
if (genend.getGeneralization().getSpecific() == specific) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether this classifier has a feature (including inherited
|
||||
* features) whose (unqualified) name matches the given matcher.
|
||||
*
|
||||
* @param matcher
|
||||
* the matcher to judge the names by.
|
||||
* @return true if the classifier has a matching feature.
|
||||
*/
|
||||
public boolean hasFeatureMatching(@Nonnull final Matcher matcher) {
|
||||
for (Feature feature : getAllFeatures()) {
|
||||
String name = feature.getName();
|
||||
if (name != null) {
|
||||
matcher.reset(name);
|
||||
if (matcher.matches())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether this classifier introduces a feature whose (unqualified)
|
||||
* name matches the given matcher.
|
||||
*
|
||||
* @param matcher
|
||||
* the matcher to judge the names by.
|
||||
* @return true if the classifier introduces a matching feature.
|
||||
*/
|
||||
public boolean introducesFeatureMatching(@Nonnull final Matcher matcher) {
|
||||
for (Feature feature : getFeatures()) {
|
||||
String name = feature.getName();
|
||||
if (name != null) {
|
||||
matcher.reset(name);
|
||||
if (matcher.matches())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
public class Comment extends MimElement {
|
||||
private String body;
|
||||
|
||||
public String getBody() {
|
||||
return this.body;
|
||||
}
|
||||
|
||||
public void setBody(final String body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public MimElement getAnnotatedElement() {
|
||||
return getOwner();
|
||||
}
|
||||
|
||||
public void setAnnotatedElement(final MimElement annotatedElement) {
|
||||
this.setOwner(annotatedElement);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
/**
|
||||
* DataType is an abstract class that acts as a common superclass for different
|
||||
* kinds of data types.
|
||||
*/
|
||||
public interface DataType extends MimType {
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class Dependencies implements Dependent {
|
||||
private Set<String> identifierDependencies;
|
||||
|
||||
public Dependencies() {
|
||||
this.identifierDependencies = new HashSet<String>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean depdendsOnIdentifier(final String name) {
|
||||
if (this.identifierDependencies == null) {
|
||||
return false;
|
||||
}
|
||||
return this.identifierDependencies.contains(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addIdentifierDependency(final String name) {
|
||||
if (this.identifierDependencies == null) {
|
||||
this.identifierDependencies = new HashSet<String>();
|
||||
}
|
||||
this.identifierDependencies.add(name);
|
||||
}
|
||||
|
||||
public Set<String> getIdentifierDependencies() {
|
||||
return this.identifierDependencies;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
/**
|
||||
* Interface to an element which is depending on some other elements. Provides a
|
||||
* list of elements the element depends on and a means of extending the list.
|
||||
*/
|
||||
public interface Dependent {
|
||||
|
||||
boolean depdendsOnIdentifier(final String name);
|
||||
|
||||
void addIdentifierDependency(final String name);
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A directed relationship references one or more source elements and one or
|
||||
* more target elements. DirectedRelationship is an abstract metaclass.
|
||||
*/
|
||||
public interface DirectedRelationship extends Relationship {
|
||||
|
||||
List<MimElement> getSourceElements();
|
||||
|
||||
List<MimElement> getTargetElements();
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* An enumeration defines a set of literals that can be used as its values.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* An enumeration defines a finite ordered set of values, such as {red, green,
|
||||
* blue}. The values denoted by typed elements whose type is an enumeration must
|
||||
* be taken from this set.
|
||||
* </p>
|
||||
*/
|
||||
public class Enumeration extends NamedElement implements DataType {
|
||||
|
||||
private Namespace owner;
|
||||
private List<EnumerationLiteral> ownedLiterals;
|
||||
|
||||
public Enumeration() {
|
||||
this.ownedLiterals = new ArrayList<EnumerationLiteral>();
|
||||
}
|
||||
|
||||
public List<EnumerationLiteral> getOwnedLiterals() {
|
||||
return this.ownedLiterals;
|
||||
}
|
||||
|
||||
public void setOwner(final Namespace owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean conformsTo(final MimType other) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MimElement getOwner() {
|
||||
return this.owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MimPackage getPackage() {
|
||||
return getOwnerAs(MimPackage.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPackage(final MimPackage owner) {
|
||||
this.setOwner(owner);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
/**
|
||||
* An enumeration literal is a value of an enumeration.
|
||||
*/
|
||||
public class EnumerationLiteral extends NamedElement {
|
||||
|
||||
private Enumeration enumeration;
|
||||
|
||||
public Enumeration getEnumeration() {
|
||||
return this.enumeration;
|
||||
}
|
||||
|
||||
public void setEnumeration(final Enumeration enumeration) {
|
||||
this.enumeration = enumeration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MimElement getOwner() {
|
||||
return this.enumeration;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
/**
|
||||
* A naming strategy which compares names exactly.
|
||||
*/
|
||||
public class ExactNamingStrategy implements NamingStrategy {
|
||||
|
||||
private static final ExactNamingStrategy INSTANCE = new ExactNamingStrategy();
|
||||
|
||||
@Override
|
||||
public boolean isSameName(final String firstName, final String secondName) {
|
||||
return StringUtils.equals(firstName, secondName);
|
||||
}
|
||||
|
||||
public static NamingStrategy getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* An extension is used to indicate that the properties of a metaclass are
|
||||
* extended through a stereotype, and gives the ability to flexibly add (and
|
||||
* later remove) stereotypes to classes.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Extension is a kind of Association. One end of the Extension is an ordinary
|
||||
* Property and the other end is an ExtensionEnd. The former ties the Extension
|
||||
* to a Class, while the latter ties the Extension to a Stereotype that extends
|
||||
* the Class.
|
||||
* </p>
|
||||
*/
|
||||
public class Extension extends Association {
|
||||
|
||||
public MimClass getMetaClass() {
|
||||
return (MimClass) getFirstNonOwnedEnd().getType();
|
||||
}
|
||||
|
||||
private Property getFirstNonOwnedEnd() {
|
||||
for (Property prop : getMemberEnds()) {
|
||||
if (!prop.isOwnedBy(this)) {
|
||||
return prop;
|
||||
}
|
||||
}
|
||||
throw new MetaModelRuntimeException(String.format(
|
||||
"%s does not contain a non-owned member end.", getName()));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
public class ExtensionEnd extends Property {
|
||||
|
||||
@Override
|
||||
public Stereotype getType() {
|
||||
return (Stereotype) super.getType();
|
||||
}
|
||||
|
||||
public void setType(final Stereotype type) {
|
||||
super.setType(type);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
/**
|
||||
* A feature declares a behavioral or structural characteristic of instances of
|
||||
* classifiers.
|
||||
*/
|
||||
public abstract class Feature extends NamedElement {
|
||||
private Classifier featuringClassifier;
|
||||
|
||||
public Classifier getFeaturingClassifier() {
|
||||
return this.featuringClassifier;
|
||||
}
|
||||
|
||||
public void setFeaturingClassifier(final Classifier featuringClassifier) {
|
||||
this.featuringClassifier = featuringClassifier;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A generalization is a taxonomic relationship between a more general
|
||||
* classifier and a more specific classifier. Each instance of the specific
|
||||
* classifier is also an instance of the general classifier. Thus, the specific
|
||||
* classifier indirectly has features of the more general classifier.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* A generalization relates a specific classifier to a more general classifier,
|
||||
* and is owned by the specific classifier.
|
||||
* </p>
|
||||
*/
|
||||
public class Generalization extends MimElement implements DirectedRelationship {
|
||||
private GeneralizationEnd generalEnd;
|
||||
private GeneralizationEnd specificEnd;
|
||||
|
||||
public Classifier getSpecific() {
|
||||
return this.specificEnd.getClassifier();
|
||||
}
|
||||
|
||||
public void setSpecific(final Classifier specific) {
|
||||
if (this.specificEnd == null) {
|
||||
this.specificEnd = new GeneralizationEnd();
|
||||
this.specificEnd.setGeneralization(this);
|
||||
}
|
||||
if (this.specificEnd.getClassifier() != null) {
|
||||
this.specificEnd.getClassifier().removeGeneral(this.specificEnd);
|
||||
}
|
||||
this.specificEnd.setClassifier(specific);
|
||||
specific.addGeneral(this.specificEnd);
|
||||
}
|
||||
|
||||
public Classifier getGeneral() {
|
||||
return this.generalEnd.getClassifier();
|
||||
}
|
||||
|
||||
public void setGeneral(final Classifier general) {
|
||||
if (this.generalEnd == null) {
|
||||
this.generalEnd = new GeneralizationEnd();
|
||||
this.generalEnd.setGeneralization(this);
|
||||
}
|
||||
if (this.generalEnd.getClassifier() != null) {
|
||||
this.generalEnd.getClassifier().removeSpecific(this.generalEnd);
|
||||
}
|
||||
this.generalEnd.setClassifier(general);
|
||||
general.addSpecific(this.generalEnd);
|
||||
}
|
||||
|
||||
public GeneralizationEnd getGeneralEnd() {
|
||||
return this.generalEnd;
|
||||
}
|
||||
|
||||
public void setGeneralEnd(final GeneralizationEnd generalEnd) {
|
||||
this.generalEnd = generalEnd;
|
||||
}
|
||||
|
||||
public GeneralizationEnd getSpecificEnd() {
|
||||
return this.specificEnd;
|
||||
}
|
||||
|
||||
public void setSpecificEnd(final GeneralizationEnd specificEnd) {
|
||||
this.specificEnd = specificEnd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MimElement> getRelatedElements() {
|
||||
List<MimElement> result = new ArrayList<MimElement>();
|
||||
result.add(getSpecific());
|
||||
result.add(getGeneral());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MimElement> getSourceElements() {
|
||||
List<MimElement> result = new ArrayList<MimElement>();
|
||||
result.add(getSpecific());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MimElement> getTargetElements() {
|
||||
List<MimElement> result = new ArrayList<MimElement>();
|
||||
result.add(getGeneral());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Generalization";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
public class GeneralizationEnd extends MimElement {
|
||||
|
||||
private Classifier classifier;
|
||||
private Generalization generalization;
|
||||
|
||||
public void setGeneralization(final Generalization generalization) {
|
||||
this.generalization = generalization;
|
||||
}
|
||||
|
||||
public Classifier getClassifier() {
|
||||
return this.classifier;
|
||||
}
|
||||
|
||||
public void setClassifier(final Classifier classifier) {
|
||||
this.classifier = classifier;
|
||||
}
|
||||
|
||||
public Generalization getGeneralization() {
|
||||
return this.generalization;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("GeneralizationEnd [classifier=").append(this.classifier).append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
public class MetaModelException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public MetaModelException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
public class MetaModelRuntimeException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public MetaModelRuntimeException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public MetaModelRuntimeException(final String message, final Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public MetaModelRuntimeException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public MetaModelRuntimeException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,195 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A class is a type that has objects as its instances.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Classes have attributes and operations and participate in inheritance
|
||||
* hierarchies. Multiple inheritance is allowed. The instances of a class are
|
||||
* objects. When a class is abstract it cannot have any direct instances. Any
|
||||
* direct instance of a concrete (i.e., non-abstract) class is also an indirect
|
||||
* instance of its class's superclasses. An object has a slot for each of its
|
||||
* class's direct and inherited attributes. An object permits the invocation of
|
||||
* operations defined in its class and its class's superclasses. The context of
|
||||
* such an invocation is the invoked object.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* A class cannot access private features of another class, or protected
|
||||
* features on another class that is not its supertype. When creating and
|
||||
* deleting associations, at least one end must allow access to the class.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The purpose of a class is to specify a classification of objects and to
|
||||
* specify the features that characterize the structure and behavior of those
|
||||
* objects.
|
||||
* </p>
|
||||
* <p>
|
||||
* Objects of a class must contain values for each attribute that is a member of
|
||||
* that class, in accordance with the characteristics of the attribute, for
|
||||
* example its type and multiplicity. When an object is instantiated in a class,
|
||||
* for every attribute of the class that has a specified default, if an initial
|
||||
* value of the attribute is not specified explicitly for the instantiation,
|
||||
* then the default value specification is evaluated to set the initial value of
|
||||
* the attribute for the object.
|
||||
* </p>
|
||||
* <p>
|
||||
* Operations of a class can be invoked on an object, given a particular set of
|
||||
* substitutions for the parameters of the operation. An operation invocation
|
||||
* may cause changes to the values of the attributes of that object. It may also
|
||||
* return a value as a result, where a result type for the operation has been
|
||||
* defined. Operation invocations may also cause changes in value to the
|
||||
* attributes of other objects that can be navigated to, directly or indirectly,
|
||||
* from the object on which the operation is invoked, to its output parameters,
|
||||
* to objects navigable from its parameters, or to other objects in the scope of
|
||||
* the operation’s execution. Operation invocations may also cause the creation
|
||||
* and deletion of objects.
|
||||
* </p>
|
||||
*/
|
||||
public class MimClass extends Classifier implements MimType, Dependent {
|
||||
|
||||
private List<Property> ownedAttributes;
|
||||
private List<Operation> ownedOperations;
|
||||
private boolean abstractFlag;
|
||||
private Dependencies dependencies;
|
||||
|
||||
public MimClass() {
|
||||
this.ownedAttributes = new ArrayList<Property>();
|
||||
this.ownedOperations = new ArrayList<Operation>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAbstract() {
|
||||
return this.abstractFlag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAbstract(final boolean value) {
|
||||
this.abstractFlag = value;
|
||||
}
|
||||
|
||||
public MimPackage getOwningPackage() {
|
||||
return getOwnerAs(MimPackage.class);
|
||||
}
|
||||
|
||||
public void setOwningPackage(final MimPackage owningPackage) {
|
||||
this.setOwner(owningPackage);
|
||||
}
|
||||
|
||||
public List<Property> getOwnedAttributes() {
|
||||
return this.ownedAttributes;
|
||||
}
|
||||
|
||||
public List<Operation> getOwnedOperations() {
|
||||
return this.ownedOperations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean conformsTo(final MimType other) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<MimClass> getSuperClasses() {
|
||||
List<MimClass> result = new ArrayList<MimClass>();
|
||||
List<Classifier> generals = getGenerals();
|
||||
for (Classifier general : generals) {
|
||||
if (general instanceof MimClass) {
|
||||
result.add((MimClass) general);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void contributeFeatures(final List<Feature> list) {
|
||||
super.contributeFeatures(list);
|
||||
list.addAll(this.ownedAttributes);
|
||||
list.addAll(this.ownedOperations);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void contributeOwnedMembers(final List<NamedElement> list) {
|
||||
list.addAll(this.ownedAttributes);
|
||||
list.addAll(this.ownedOperations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MimPackage getPackage() {
|
||||
return getOwningPackage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPackage(final MimPackage owner) {
|
||||
this.setOwner(owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOwnedMember(final NamedElement member) {
|
||||
if (member instanceof Property) {
|
||||
this.ownedAttributes.add((Property) member);
|
||||
} else if (member instanceof Operation) {
|
||||
this.ownedOperations.add((Operation) member);
|
||||
} else {
|
||||
throw new RuntimeException(
|
||||
String.format(
|
||||
"A class can only own elements of type Property or Operation, but the given element is of type %s.",
|
||||
member.getClass().getSimpleName()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeOwnedMember(final NamedElement member) {
|
||||
this.ownedAttributes.remove(member);
|
||||
this.ownedOperations.remove(member);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given stereotype as a new stereotype of this class.
|
||||
*
|
||||
* @param stereotype
|
||||
* the stereotype to add.
|
||||
*/
|
||||
public void addStereotype(final Stereotype stereotype) {
|
||||
Extension ext = new Extension();
|
||||
ExtensionEnd ee = new ExtensionEnd();
|
||||
ee.setType(stereotype);
|
||||
Property prop = new Property();
|
||||
prop.setType(this);
|
||||
ext.addMember(ee);
|
||||
ext.addOwnedMember(prop);
|
||||
addOwnedMember(prop);
|
||||
stereotype.addNonOwnedFeature(ee);
|
||||
getOwnerAs(Namespace.class).addOwnedMember(ext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean depdendsOnIdentifier(final String name) {
|
||||
if (this.dependencies == null) {
|
||||
return false;
|
||||
}
|
||||
return this.dependencies.depdendsOnIdentifier(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addIdentifierDependency(final String name) {
|
||||
if (this.dependencies == null) {
|
||||
this.dependencies = new Dependencies();
|
||||
}
|
||||
this.dependencies.addIdentifierDependency(name);
|
||||
}
|
||||
|
||||
public Set<String> getIdentifierDependencies() {
|
||||
if (this.dependencies == null) {
|
||||
return new HashSet<String>();
|
||||
}
|
||||
return this.dependencies.getIdentifierDependencies();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Element is an abstract metaclass with no superclass. It is used as the common
|
||||
* superclass for all metaclasses in the infrastructure library. Element has a
|
||||
* derived composition association to itself to support the general capability
|
||||
* for elements to own other elements.
|
||||
*/
|
||||
public abstract class MimElement {
|
||||
|
||||
private List<Comment> ownedComments;
|
||||
private MimElement owner;
|
||||
|
||||
public MimElement getOwner() {
|
||||
return this.owner;
|
||||
}
|
||||
|
||||
public void setOwner(final MimElement owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getOwnerAs(final java.lang.Class<T> elementType) {
|
||||
if (this.owner == null)
|
||||
return null;
|
||||
if (!elementType.isAssignableFrom(this.owner.getClass())) {
|
||||
throw new RuntimeException(String.format(
|
||||
"The owner of %s is not of the desired type \"%s\".", toString(), elementType
|
||||
.getClass().getSimpleName()));
|
||||
}
|
||||
return (T) this.owner;
|
||||
}
|
||||
|
||||
public final List<MimElement> getOwnedElements() {
|
||||
List<MimElement> result = new ArrayList<MimElement>();
|
||||
contributeOwnedElements(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void contributeOwnedElements(final List<MimElement> result) {
|
||||
result.addAll(this.ownedComments);
|
||||
}
|
||||
|
||||
public boolean isStub() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.CheckForNull;
|
||||
|
||||
/**
|
||||
* Packages provide a way of grouping types and packages together, which can be
|
||||
* useful for understanding and managing a model. A package cannot contain
|
||||
* itself.
|
||||
*/
|
||||
public class MimPackage extends Namespace {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(MimPackage.class.getName());
|
||||
private List<NamedElement> ownedTypes;
|
||||
|
||||
public MimPackage() {
|
||||
this.ownedTypes = new ArrayList<NamedElement>();
|
||||
}
|
||||
|
||||
public List<MimType> getOwnedTypes() {
|
||||
List<MimType> result = new ArrayList<MimType>();
|
||||
for (NamedElement element : getOwnedMembers()) {
|
||||
if (element instanceof MimType) {
|
||||
result.add((MimType) element);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<MimType> getOwnedStereotypes() {
|
||||
List<MimType> result = new ArrayList<MimType>();
|
||||
for (NamedElement element : getOwnedMembers()) {
|
||||
if (element instanceof Stereotype) {
|
||||
result.add((Stereotype) element);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<MimPackage> getNestedPackages() {
|
||||
List<MimPackage> result = new ArrayList<MimPackage>();
|
||||
for (NamedElement element : getOwnedMembers()) {
|
||||
if (element instanceof MimPackage) {
|
||||
result.add((MimPackage) element);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public MimPackage getNestingPackage() {
|
||||
return getOwnerAs(MimPackage.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void contributeOwnedMembers(final List<NamedElement> list) {
|
||||
list.addAll(this.ownedTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void contributeOwnedElements(final List<MimElement> result) {
|
||||
result.addAll(this.ownedTypes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void contributeAllMembers(final List<NamedElement> list) {
|
||||
super.contributeAllMembers(list);
|
||||
for (MimPackage nested : getNestedPackages()) {
|
||||
nested.contributeAllMembers(list);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOwnedMember(final NamedElement member) {
|
||||
this.ownedTypes.add(member);
|
||||
member.setOwner(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeOwnedMember(final NamedElement member) {
|
||||
this.ownedTypes.remove(member);
|
||||
if (member.getOwner() == this) {
|
||||
member.setOwner(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a package import for the given package name, which makes the names
|
||||
* of that package available within this package.
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
public void addPackageImportStub(final String name) {
|
||||
PackageImport imp = new PackageImport();
|
||||
imp.setImportingNamespace(this);
|
||||
StubPackage target = new StubPackage(imp);
|
||||
target.setName(name);
|
||||
imp.setImportedPackage(target);
|
||||
addPackageImport(imp);
|
||||
target.addImportingPackage(imp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates any package nested in this package by name.
|
||||
*
|
||||
* @param name
|
||||
* the package name.
|
||||
* @return a reference to the package with this name, or null.
|
||||
*/
|
||||
@CheckForNull
|
||||
public MimPackage findContainedPackage(final String name) {
|
||||
if (name.equalsIgnoreCase(getName())) {
|
||||
return this;
|
||||
}
|
||||
for (MimPackage detail : getOwnedMembersOfType(MimPackage.class)) {
|
||||
MimPackage found = detail.findContainedPackage(name);
|
||||
if (found != null) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void collectOwnedClasses(final Set<MimClass> elementSet) {
|
||||
{
|
||||
List<MimClass> elements = getOwnedMembersOfType(MimClass.class);
|
||||
for (MimClass mimClass : elements) {
|
||||
elementSet.add(mimClass);
|
||||
}
|
||||
}
|
||||
for (MimPackage detail : getNestedPackages()) {
|
||||
detail.collectOwnedClasses(elementSet);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<MimClass> getAllOwnedClasses() {
|
||||
Set<MimClass> result = new LinkedHashSet<MimClass>();
|
||||
collectOwnedClasses(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void collectPackages(final List<MimPackage> elementSet) {
|
||||
{
|
||||
List<MimPackage> elements = getOwnedMembersOfType(MimPackage.class);
|
||||
for (MimPackage mimClass : elements) {
|
||||
elementSet.add(mimClass);
|
||||
}
|
||||
}
|
||||
for (MimPackage detail : getNestedPackages()) {
|
||||
detail.collectPackages(elementSet);
|
||||
}
|
||||
}
|
||||
|
||||
public List<MimPackage> getAllOwnedPackages() {
|
||||
List<MimPackage> result = new ArrayList<MimPackage>();
|
||||
collectPackages(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public Map<String, MimPackage> getAllOwnedNonStubPackages(final boolean lowercaseKeys) {
|
||||
List<MimPackage> allPackages = getAllOwnedPackages();
|
||||
return removeStubs(allPackages, lowercaseKeys);
|
||||
}
|
||||
|
||||
public Map<String, MimClass> getAllNonStubClasses(final boolean lowercaseKeys) {
|
||||
List<MimClass> allClasses = getAllMembersOfType(MimClass.class);
|
||||
return removeStubs(allClasses, lowercaseKeys);
|
||||
}
|
||||
|
||||
protected <T extends NamedElement> Map<String, T> removeStubs(final List<T> elements,
|
||||
final boolean lowercaseKeys) {
|
||||
Map<String, T> result = new HashMap<String, T>();
|
||||
for (T element : elements) {
|
||||
if (!element.isStub()) {
|
||||
String key = element.getName();
|
||||
if (lowercaseKeys)
|
||||
key = key.toLowerCase();
|
||||
result.put(key, element);
|
||||
} else {
|
||||
LOGGER.info(String.format("Stub %s was filtered out.", element.getName()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
public interface MimType {
|
||||
public abstract boolean conformsTo(MimType other);
|
||||
|
||||
public MimPackage getPackage();
|
||||
|
||||
public void setPackage(MimPackage owner);
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
public class Multiplicity {
|
||||
// isOrdered
|
||||
// isUnique
|
||||
private int lower;
|
||||
private int upper;
|
||||
|
||||
public Multiplicity() {
|
||||
this.lower = 1;
|
||||
this.upper = 1;
|
||||
}
|
||||
|
||||
public int getLower() {
|
||||
return this.lower;
|
||||
}
|
||||
|
||||
public void setLower(final int lower) {
|
||||
this.lower = lower;
|
||||
}
|
||||
|
||||
public int getUpper() {
|
||||
return this.upper;
|
||||
}
|
||||
|
||||
public void setUpper(final int upper) {
|
||||
this.upper = upper;
|
||||
}
|
||||
|
||||
public boolean isMultiValued() {
|
||||
return this.upper == 0 || this.upper > 1;
|
||||
}
|
||||
|
||||
public boolean includesCardinality(final int value) {
|
||||
boolean lowerMet = value >= this.lower;
|
||||
if (this.upper == 0) {
|
||||
return lowerMet;
|
||||
}
|
||||
return lowerMet && value <= this.upper;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
|
||||
public interface MultiplicityElement {
|
||||
|
||||
Multiplicity getMultiplicity();
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
|
||||
/**
|
||||
* A named element represents elements that may have a name. The name is used
|
||||
* for identification of the named element within the namespace in which it is
|
||||
* defined. A named element also has a qualified name that allows it to be
|
||||
* unambiguously identified within a hierarchy of nested namespaces.
|
||||
* NamedElement is an abstract metaclass.
|
||||
*
|
||||
* The name for a named element is optional. If specified, then any valid
|
||||
* string, including the empty string, may be used.
|
||||
*/
|
||||
public abstract class NamedElement extends MimElement {
|
||||
private String name;
|
||||
private VisibilityKind visibility;
|
||||
|
||||
public VisibilityKind getVisibility() {
|
||||
return this.visibility;
|
||||
}
|
||||
|
||||
public void setVisibility(final VisibilityKind visibility) {
|
||||
this.visibility = visibility;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Namespace getNamespace() {
|
||||
MimElement owner = getOwner();
|
||||
if (owner instanceof Namespace)
|
||||
return (Namespace) owner;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A name which allows the NamedElement to be identified within a hierarchy
|
||||
* of nested Namespaces. It is constructed from the names of the containing
|
||||
* namespaces starting at the root of the hierarchy and ending with the name
|
||||
* of the NamedElement itself. This is a derived attribute.
|
||||
*
|
||||
* @return the qualified name.
|
||||
*/
|
||||
public String getQualifiedName() {
|
||||
Namespace ns = getNamespace();
|
||||
if (ns == null) {
|
||||
return this.name;
|
||||
}
|
||||
return ns.getQualifiedName() + '.' + this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(getClass().getSimpleName()).append(" ").append(getQualifiedName());
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,242 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* A namespace is a named element that can own other named elements. Each named
|
||||
* element may be owned by at most one namespace. A namespace provides a means
|
||||
* for identifying named elements by name. Named elements can be identified by
|
||||
* name in a namespace either by being directly owned by the namespace or by
|
||||
* being introduced into the namespace by other means (e.g., importing or
|
||||
* inheriting). Namespace is an abstract metaclass.
|
||||
*/
|
||||
public abstract class Namespace extends NamedElement {
|
||||
|
||||
private List<PackageImport> packageImports;
|
||||
private List<PackageImport> importingPackages;
|
||||
private NamingStrategy namingStrategy;
|
||||
|
||||
public Namespace() {
|
||||
super();
|
||||
this.packageImports = new ArrayList<PackageImport>();
|
||||
this.importingPackages = new ArrayList<PackageImport>();
|
||||
this.namingStrategy = ExactNamingStrategy.getInstance();
|
||||
}
|
||||
|
||||
public NamingStrategy getNamingStrategy() {
|
||||
return this.namingStrategy;
|
||||
}
|
||||
|
||||
public void setNamingStrategy(final NamingStrategy namingStrategy) {
|
||||
this.namingStrategy = namingStrategy;
|
||||
}
|
||||
|
||||
public List<PackageImport> getPackageImports() {
|
||||
return this.packageImports;
|
||||
}
|
||||
|
||||
public List<PackageImport> getImportingPackages() {
|
||||
return this.importingPackages;
|
||||
}
|
||||
|
||||
public void addPackageImport(@Nonnull final PackageImport imp) {
|
||||
this.packageImports.add(imp);
|
||||
}
|
||||
|
||||
public void removePackageImport(@Nonnull final PackageImport imp) {
|
||||
this.packageImports.remove(imp);
|
||||
}
|
||||
|
||||
public void addImportingPackage(@Nonnull final PackageImport imp) {
|
||||
this.importingPackages.add(imp);
|
||||
}
|
||||
|
||||
public void removeImportingPackage(@Nonnull final PackageImport imp) {
|
||||
this.importingPackages.remove(imp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the elements directly owned by this namespace.
|
||||
*
|
||||
* @return the list of owned elements.
|
||||
*/
|
||||
public List<NamedElement> getOwnedMembers() {
|
||||
List<NamedElement> result = new ArrayList<NamedElement>();
|
||||
contributeOwnedMembers(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected abstract void contributeOwnedMembers(final List<NamedElement> list);
|
||||
|
||||
/**
|
||||
* A collection of NamedElements identifiable within the Namespace, either
|
||||
* by being owned or by being introduced by importing or inheritance. This
|
||||
* is a derived union.
|
||||
*
|
||||
* @return the complete list of members contained in this namespace.
|
||||
*/
|
||||
public List<NamedElement> getMembers() {
|
||||
List<NamedElement> result = new ArrayList<NamedElement>();
|
||||
contributeMembers(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected List<NamedElement> getAllMembers() {
|
||||
List<NamedElement> result = new ArrayList<NamedElement>();
|
||||
contributeAllMembers(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<MimPackage> getImportedPackages() {
|
||||
List<MimPackage> result = new ArrayList<MimPackage>();
|
||||
for (PackageImport imp : this.packageImports) {
|
||||
if (imp.getImportedPackage() == null) {
|
||||
throw new MetaModelRuntimeException(
|
||||
"Invalid package import: Imported package is null.");
|
||||
}
|
||||
result.add(imp.getImportedPackage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void contributeMembers(final List<NamedElement> list) {
|
||||
list.addAll(getOwnedMembers());
|
||||
for (MimPackage importedPackage : getImportedPackages()) {
|
||||
list.addAll(importedPackage.getOwnedMembers());
|
||||
}
|
||||
}
|
||||
|
||||
protected void contributeAllMembers(final List<NamedElement> list) {
|
||||
contributeMembers(list);
|
||||
}
|
||||
|
||||
public NamedElement getMemberByName(final String name) throws UnknownMemberException {
|
||||
NamedElement member = findMember(name);
|
||||
if (member == null) {
|
||||
throw new UnknownMemberException(String.format(
|
||||
"Element \"%s\" does not have a member element with name \"%s\".", getName(),
|
||||
name));
|
||||
}
|
||||
return member;
|
||||
}
|
||||
|
||||
public <T extends NamedElement> T getMemberOfTypeByName(final java.lang.Class<T> type,
|
||||
final String name) throws UnknownMemberException {
|
||||
T member = findMemberOfType(type, name);
|
||||
if (member == null) {
|
||||
throw new UnknownMemberException(String.format(
|
||||
"Element \"%s\" does not have a member element with name \"%s\".", getName(),
|
||||
name));
|
||||
}
|
||||
return member;
|
||||
}
|
||||
|
||||
public NamedElement getOwnedMemberByName(final String name) throws UnknownMemberException {
|
||||
NamedElement member = findOwnedMember(name);
|
||||
if (member == null) {
|
||||
throw new UnknownMemberException(String.format(
|
||||
"Element \"%s\" does not own an element with name \"%s\".", getName(), name));
|
||||
}
|
||||
return member;
|
||||
}
|
||||
|
||||
public NamedElement findMember(final String name) {
|
||||
return findByName(getMembers(), name);
|
||||
}
|
||||
|
||||
public <T extends NamedElement> T findMemberOfType(final java.lang.Class<T> type,
|
||||
final String name) {
|
||||
List<T> elements = getMembersOfType(type);
|
||||
return findByName(elements, name);
|
||||
}
|
||||
|
||||
public <T extends NamedElement> List<T> getMembersOfType(final java.lang.Class<T> type) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<T> elements = (List<T>) getMembers();
|
||||
return filterByElementType(elements, type);
|
||||
}
|
||||
|
||||
public <T extends NamedElement> List<T> getAllMembersOfType(final java.lang.Class<T> type) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<T> elements = (List<T>) getAllMembers();
|
||||
return filterByElementType(elements, type);
|
||||
}
|
||||
|
||||
protected <T extends NamedElement> T findByName(final List<T> elements, final String name) {
|
||||
for (T element : elements) {
|
||||
if (this.namingStrategy.isSameName(name, element.getName())) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public NamedElement findOwnedMember(final String name) {
|
||||
for (NamedElement element : getOwnedMembers()) {
|
||||
if (this.namingStrategy.isSameName(name, element.getName())) {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T findOwnedMemberAs(final String name, final java.lang.Class<T> elementType) {
|
||||
NamedElement detailMember = findOwnedMember(name);
|
||||
if (detailMember != null) {
|
||||
if (!elementType.isAssignableFrom(detailMember.getClass())) {
|
||||
throw new RuntimeException(String.format(
|
||||
"Element \"%s\" contained in \"%s\" is not of type %s.", name, getName(),
|
||||
elementType.getClass().getSimpleName()));
|
||||
}
|
||||
return (T) detailMember;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends NamedElement> List<T> getOwnedMembersOfType(
|
||||
final java.lang.Class<T> memberClass) {
|
||||
List<T> members = (List<T>) getOwnedMembers();
|
||||
return filterByElementType(members, memberClass);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T extends NamedElement> List<T> filterByElementType(final List<T> elements,
|
||||
final java.lang.Class<T> memberClass) {
|
||||
List<T> result = new ArrayList<T>();
|
||||
for (NamedElement element : elements) {
|
||||
if (memberClass.isAssignableFrom(element.getClass())) {
|
||||
result.add((T) element);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T extends MimType> List<T> filterByType(final List<NamedElement> elements,
|
||||
final java.lang.Class<T> typeClass) {
|
||||
List<T> result = new ArrayList<T>();
|
||||
for (NamedElement element : elements) {
|
||||
if (typeClass.isAssignableFrom(element.getClass())) {
|
||||
result.add((T) element);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public abstract void addOwnedMember(NamedElement member);
|
||||
|
||||
public abstract void removeOwnedMember(NamedElement member);
|
||||
|
||||
public MimType findType(final String typeName) {
|
||||
NamedElement elem = findMember(typeName);
|
||||
if (elem instanceof MimType) {
|
||||
return (MimType) elem;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
/**
|
||||
* Defines how names are compared with each other.
|
||||
*/
|
||||
public interface NamingStrategy {
|
||||
boolean isSameName(String firstName, String secondName);
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* An operation is owned by a class and may be invoked in the context of objects
|
||||
* that are instances of that class. It is a typed element and a multiplicity
|
||||
* element.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* An operation belongs to a class. It is possible to invoke an operation on any
|
||||
* object that is directly or indirectly an instance of the class. Within such
|
||||
* an invocation the execution context includes this object and the values of
|
||||
* the parameters. The type of the operation, if any, is the type of the result
|
||||
* returned by the operation, and the multiplicity is the multiplicity of the
|
||||
* result. An operation can be associated with a set of types that represent
|
||||
* possible exceptions that the operation may raise.
|
||||
* </p>
|
||||
*/
|
||||
public class Operation extends Feature implements TypedElement, MultiplicityElement, Dependent {
|
||||
|
||||
private MimClass owningClass;
|
||||
private Multiplicity multiplicity;
|
||||
private List<Parameter> ownedParameters;
|
||||
private List<MimType> raisedExceptions;
|
||||
private Dependencies dependencies;
|
||||
|
||||
public Operation() {
|
||||
}
|
||||
|
||||
public List<Parameter> getOwnedParameters() {
|
||||
return this.ownedParameters;
|
||||
}
|
||||
|
||||
public List<MimType> getRaisedExceptions() {
|
||||
return this.raisedExceptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MimElement getOwner() {
|
||||
return this.owningClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MimType getType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setType(final MimType type) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Multiplicity getMultiplicity() {
|
||||
return this.multiplicity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean depdendsOnIdentifier(final String name) {
|
||||
if (this.dependencies == null) {
|
||||
return false;
|
||||
}
|
||||
return this.dependencies.depdendsOnIdentifier(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addIdentifierDependency(final String name) {
|
||||
if (this.dependencies == null) {
|
||||
this.dependencies = new Dependencies();
|
||||
}
|
||||
this.dependencies.addIdentifierDependency(name);
|
||||
}
|
||||
|
||||
public Set<String> getIdentifierDependencies() {
|
||||
if (this.dependencies == null) {
|
||||
return new HashSet<String>();
|
||||
}
|
||||
return this.dependencies.getIdentifierDependencies();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A package import is a relationship that allows the use of unqualified names
|
||||
* to refer to package members from other namespaces.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* A package import is a relationship between an importing namespace and a
|
||||
* package, indicating that the importing namespace adds the names of the
|
||||
* members of the package to its own namespace. Conceptually, a package import
|
||||
* is equivalent to having an element import to each individual member of the
|
||||
* imported namespace, unless there is already a separately-defined element
|
||||
* import.
|
||||
* </p>
|
||||
*/
|
||||
public class PackageImport extends MimElement implements DirectedRelationship {
|
||||
private MimPackage importedPackage;
|
||||
|
||||
/**
|
||||
* Specifies the Package whose members are imported into a Namespace.
|
||||
* Subsets {@link DirectedRelationship#getTargetElements()}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public MimPackage getImportedPackage() {
|
||||
return this.importedPackage;
|
||||
}
|
||||
|
||||
public void setImportedPackage(final MimPackage importedPackage) {
|
||||
this.importedPackage = importedPackage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the Namespace that imports the members from a Package. Subsets
|
||||
* {@link DirectedRelationship#getSourceElements()} and Element::owner.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Namespace getImportingNamespace() {
|
||||
return this.getOwnerAs(Namespace.class);
|
||||
}
|
||||
|
||||
public void setImportingNamespace(final Namespace importingNamespace) {
|
||||
this.setOwner(importingNamespace);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MimElement> getRelatedElements() {
|
||||
List<MimElement> result = new ArrayList<MimElement>();
|
||||
result.add(getImportingNamespace());
|
||||
result.add(getImportedPackage());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MimElement> getSourceElements() {
|
||||
List<MimElement> result = new ArrayList<MimElement>();
|
||||
result.add(getImportingNamespace());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MimElement> getTargetElements() {
|
||||
List<MimElement> result = new ArrayList<MimElement>();
|
||||
result.add(getImportedPackage());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("PackageImport [importingNamespace=").append(getImportingNamespace())
|
||||
.append(", importedPackage=").append(getImportedPackage()).append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A parameter is a typed element that represents a parameter of an operation.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* When an operation is invoked, an argument may be passed to it for each
|
||||
* parameter. Each parameter has a type and a multiplicity. Every Parameter is
|
||||
* associated with an operation, although subclasses of Parameter elsewhere in
|
||||
* the UML model do not have to be associated with an operation, hence the 0..1
|
||||
* multiplicity.
|
||||
* </p>
|
||||
*/
|
||||
public class Parameter extends NamedElement implements TypedElement, MultiplicityElement {
|
||||
private Operation operation;
|
||||
private Multiplicity multiplicity;
|
||||
private ParameterDirectionKind direction;
|
||||
|
||||
public ParameterDirectionKind getDirection() {
|
||||
return this.direction;
|
||||
}
|
||||
|
||||
public void setDirection(final ParameterDirectionKind direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public Operation getOperation() {
|
||||
return this.operation;
|
||||
}
|
||||
|
||||
public void setOperation(final Operation operation) {
|
||||
this.operation = operation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Multiplicity getMultiplicity() {
|
||||
return this.multiplicity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MimType getType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setType(final MimType type) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public MimElement getOwner() {
|
||||
return this.operation;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
public enum ParameterDirectionKind {
|
||||
IN, IN_OUT, OUT, RETURN
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
/**
|
||||
* A primitive type is a data type implemented by the underlying infrastructure
|
||||
* and made available for modeling.
|
||||
*/
|
||||
public class PrimitiveType extends NamedElement implements DataType {
|
||||
|
||||
@Override
|
||||
public boolean conformsTo(final MimType other) {
|
||||
return this == other;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MimPackage getPackage() {
|
||||
return getOwnerAs(MimPackage.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPackage(final MimPackage owner) {
|
||||
setOwner(owner);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
public class Profile extends MimPackage implements NamingStrategy {
|
||||
|
||||
@Override
|
||||
public boolean isSameName(final String firstName, final String secondName) {
|
||||
return StringUtils.equals(firstName, secondName);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import javax.annotation.CheckForNull;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A property represents an attribute of a class. A property has a type and a
|
||||
* multiplicity. When a property is paired with an opposite they represent two
|
||||
* mutually constrained attributes. The semantics of two properties that are
|
||||
* mutual opposites are the same as for bidirectionally navigable associations
|
||||
* in Constructs, with the exception that the association has no explicit links
|
||||
* as instances, and has no name.
|
||||
* </p>
|
||||
*/
|
||||
public class Property extends StructuralFeature implements TypedElement, MultiplicityElement {
|
||||
|
||||
private Relationship owningRelationship;
|
||||
private Relationship relationship;
|
||||
private Multiplicity multiplicity;
|
||||
private String defaultValue;
|
||||
private boolean composite;
|
||||
private boolean derived;
|
||||
private boolean readOnly;
|
||||
private Property opposite;
|
||||
private MimType type;
|
||||
|
||||
public Property() {
|
||||
this.multiplicity = new Multiplicity();
|
||||
}
|
||||
|
||||
/**
|
||||
* References the owning relationship of this property, if any.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Relationship getOwningRelationship() {
|
||||
return this.owningRelationship;
|
||||
}
|
||||
|
||||
/**
|
||||
* References the Class that owns the Property. Subsets
|
||||
* {@link NamedElement#getNamespace()},
|
||||
* {@link Feature#getFeaturingClassifier()}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public MimClass getOwningClass() {
|
||||
MimElement owner = this.getOwner();
|
||||
if (owner == null)
|
||||
return null;
|
||||
if (!(owner instanceof MimClass))
|
||||
throw new MetaModelRuntimeException(String.format("%s is not owned by a class.",
|
||||
toString()));
|
||||
return (MimClass) owner;
|
||||
}
|
||||
|
||||
public void setOwningClass(final MimClass owningClass) {
|
||||
this.setOwner(owningClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* References the relationship of which this property is a member, if any.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@CheckForNull
|
||||
public Relationship getRelationship() {
|
||||
return this.relationship;
|
||||
}
|
||||
|
||||
public void setAssociation(final Association association) {
|
||||
this.relationship = association;
|
||||
}
|
||||
|
||||
/**
|
||||
* Two attributes attr1 and attr2 of two objects o1 and o2 (which may be the
|
||||
* same object) may be paired with each other so that o1.attr1 refers to o2
|
||||
* if and only if o2.attr2 refers to o1. In such a case attr1 is the
|
||||
* opposite of attr2 and attr2 is the opposite of attr1.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Property getOpposite() {
|
||||
return this.opposite;
|
||||
}
|
||||
|
||||
public void setOpposite(final Property opposite) {
|
||||
this.opposite = opposite;
|
||||
}
|
||||
|
||||
/**
|
||||
* If isReadOnly is true, the attribute may not be written to after
|
||||
* initialization. The default value is false.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isReadOnly() {
|
||||
return this.readOnly;
|
||||
}
|
||||
|
||||
public void setReadOnly(final boolean readOnly) {
|
||||
this.readOnly = readOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* If isComposite is true, the object containing the attribute is a
|
||||
* container for the object or value contained in the attribute. The default
|
||||
* value is false.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isComposite() {
|
||||
return this.composite;
|
||||
}
|
||||
|
||||
public void setComposite(final boolean composite) {
|
||||
this.composite = composite;
|
||||
}
|
||||
|
||||
/**
|
||||
* If isDerived is true, the value of the attribute is derived from
|
||||
* information elsewhere. The default value is false.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isDerived() {
|
||||
return this.derived;
|
||||
}
|
||||
|
||||
public void setDerived(final boolean derived) {
|
||||
this.derived = derived;
|
||||
}
|
||||
|
||||
/**
|
||||
* A string that is evaluated to give a default value for the attribute when
|
||||
* an object of the owning class is instantiated.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getDefaultValue() {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
public void setDefaultValue(final String defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Multiplicity getMultiplicity() {
|
||||
return this.multiplicity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MimType getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setType(final MimType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public boolean isOwnedBy(final Classifier classifier) {
|
||||
return getOwner() == classifier;
|
||||
}
|
||||
|
||||
public void setRelationship(final Relationship relationship) {
|
||||
this.relationship = relationship;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Relationship is an abstract concept that specifies some kind of relationship
|
||||
* between elements.
|
||||
*/
|
||||
public interface Relationship {
|
||||
|
||||
List<MimElement> getRelatedElements();
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
public class Stereotype extends MimClass {
|
||||
|
||||
public Profile getProfile() {
|
||||
return getOwnerAs(Profile.class);
|
||||
}
|
||||
|
||||
public void setProfile(final Profile profile) {
|
||||
setOwner(profile);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
/**
|
||||
* A structural feature is a typed feature of a classifier that specifies the
|
||||
* structure of instances of the classifier.
|
||||
*/
|
||||
public abstract class StructuralFeature extends Feature implements TypedElement {
|
||||
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class StubClass extends MimClass {
|
||||
private String stubReason;
|
||||
private List<MimElement> referers;
|
||||
|
||||
public StubClass() {
|
||||
this.referers = new ArrayList<MimElement>();
|
||||
}
|
||||
|
||||
public String getStubReason() {
|
||||
return this.stubReason;
|
||||
}
|
||||
|
||||
public void setStubReason(final String stubReason) {
|
||||
this.stubReason = stubReason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("StubClass ").append(getName()).append(": ").append(this.stubReason);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes all relationship ends pointing at this stub point at the given
|
||||
* class instead.
|
||||
*
|
||||
* @param resolved
|
||||
*/
|
||||
public void replaceWith(final MimClass replacement) {
|
||||
if (replacement.isStub())
|
||||
throw new MetaModelRuntimeException(String.format(
|
||||
"Cannot replace stub %s with stub %s.", this, replacement));
|
||||
for (MimElement element : this.referers) {
|
||||
if (element instanceof Generalization) {
|
||||
((Generalization) element).setGeneral(replacement);
|
||||
}
|
||||
}
|
||||
MimPackage owner = getOwnerAs(MimPackage.class);
|
||||
owner.removeOwnedMember(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void contributeOwnedMembers(final List<NamedElement> list) {
|
||||
}
|
||||
|
||||
public void addReferer(final MimElement element) {
|
||||
this.referers.add(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStub() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
public class StubPackage extends MimPackage {
|
||||
|
||||
private PackageImport owningImport;
|
||||
|
||||
public StubPackage(final PackageImport owningImport) {
|
||||
super();
|
||||
this.owningImport = owningImport;
|
||||
}
|
||||
|
||||
public PackageImport getOwningImport() {
|
||||
return this.owningImport;
|
||||
}
|
||||
|
||||
public void replaceWith(final MimPackage resolved) {
|
||||
this.owningImport.setImportedPackage(resolved);
|
||||
removeImportingPackage(this.owningImport);
|
||||
resolved.addImportingPackage(this.owningImport);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStub() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
public class StubType extends NamedElement implements DataType {
|
||||
private String message;
|
||||
|
||||
public String getMessage() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("StubType ").append(getName()).append(": ").append(this.message);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean conformsTo(final MimType other) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MimPackage getPackage() {
|
||||
return getOwnerAs(MimPackage.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPackage(final MimPackage owner) {
|
||||
setOwner(owner);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
public interface TypedElement {
|
||||
MimType getType();
|
||||
|
||||
void setType(MimType type);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
public class UnknownMemberException extends MetaModelException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public UnknownMemberException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* VisibilityKind is intended for use in the specification of visibility in
|
||||
* conjunction with, for example, the Imports, Generalizations, Packages, and
|
||||
* Classifiers packages. Detailed semantics are specified with those mechanisms.
|
||||
* If the Visibility package is used without those packages, these literals will
|
||||
* have different meanings, or no meanings.
|
||||
* <ol>
|
||||
* <li>A public element is visible to all elements that can access the contents
|
||||
* of the namespace that owns it.</li>
|
||||
* <li>A private element is only visible inside the namespace that owns it.</li>
|
||||
* <li>A protected element is visible to elements that have a generalization
|
||||
* relationship to the namespace that owns it.</li>
|
||||
* <li>A package element is owned by a namespace that is not a package, and is
|
||||
* visible to elements that are in the same package as its owning namespace.
|
||||
* Only named elements that are not owned by packages can be marked as having
|
||||
* package visibility. Any element marked as having package visibility is
|
||||
* visible to all elements within the nearest enclosing package (given that
|
||||
* other owning elements have proper visibility). Outside the nearest enclosing
|
||||
* package, an element marked as having package visibility is not visible.</li>
|
||||
* </ol>
|
||||
* In circumstances where a named element ends up with multiple visibilities,
|
||||
* for example by being imported multiple times, public visibility overrides
|
||||
* private visibility, i.e., if an element is imported twice into the same
|
||||
* namespace, once using public import and once using private import, it will be
|
||||
* public.
|
||||
*/
|
||||
public enum VisibilityKind {
|
||||
PRIVATE, PROTECTED, PACKAGE, PUBLIC;
|
||||
|
||||
/**
|
||||
* Examines a set of VisibilityKinds, and returns PUBLIC as the preferred
|
||||
* visibility. If PUBLIC is not in the set, PRIVATE is returned.
|
||||
*
|
||||
* @param set
|
||||
* the set to examine.
|
||||
* @return the best visibility.
|
||||
*/
|
||||
public static VisibilityKind getBestVisibility(final Set<VisibilityKind> set) {
|
||||
if (set.contains(VisibilityKind.PUBLIC)) {
|
||||
return VisibilityKind.PUBLIC;
|
||||
}
|
||||
return VisibilityKind.PRIVATE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
package ch.bitwave.mim.m2.profiles;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import ch.bitwave.mim.m2.core.MetaModelRuntimeException;
|
||||
import ch.bitwave.mim.m2.core.MimClass;
|
||||
import ch.bitwave.mim.m2.core.MimPackage;
|
||||
import ch.bitwave.mim.m2.core.MimType;
|
||||
import ch.bitwave.mim.m2.core.PrimitiveType;
|
||||
import ch.bitwave.mim.m2.core.Profile;
|
||||
import ch.bitwave.mim.m2.core.Stereotype;
|
||||
|
||||
public class DelphiProfile extends Profile {
|
||||
|
||||
private final Stereotype interfaceStereotype;
|
||||
private final MimType stringType;
|
||||
private final MimType integerType;
|
||||
private final MimType booleanType;
|
||||
|
||||
Map<String, MimType> typesByName;
|
||||
|
||||
public DelphiProfile() {
|
||||
this.typesByName = new HashMap<String, MimType>();
|
||||
this.interfaceStereotype = createStereotype("interface");
|
||||
this.stringType = createPrimitiveType("string");
|
||||
this.integerType = createPrimitiveType("integer");
|
||||
this.booleanType = createPrimitiveType("boolean");
|
||||
}
|
||||
|
||||
private MimType createPrimitiveType(final String name) {
|
||||
PrimitiveType result = new PrimitiveType();
|
||||
result.setName(name);
|
||||
this.typesByName.put(name, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private Stereotype createStereotype(final String name) {
|
||||
Stereotype result = new Stereotype();
|
||||
result.setName(name);
|
||||
addOwnedMember(result);
|
||||
this.typesByName.put(name, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public Stereotype getInterfaceStereotype() {
|
||||
return this.interfaceStereotype;
|
||||
}
|
||||
|
||||
public MimType getStringType() {
|
||||
return this.stringType;
|
||||
}
|
||||
|
||||
public MimType getIntegerType() {
|
||||
return this.integerType;
|
||||
}
|
||||
|
||||
public MimType getBooleanType() {
|
||||
return this.booleanType;
|
||||
}
|
||||
|
||||
public MimType getType(@Nonnull final String typeName) {
|
||||
MimType result = findType(typeName);
|
||||
if (result == null) {
|
||||
throw new MetaModelRuntimeException(String.format(
|
||||
"The Delphi profile does not provide type \"%s\".", typeName));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MimType findType(final String typeName) {
|
||||
return this.typesByName.get(typeName.toLowerCase());
|
||||
}
|
||||
|
||||
public MimPackage createPackage(final String name) {
|
||||
MimPackage result = new MimPackage();
|
||||
result.setNamingStrategy(this);
|
||||
result.setName(name);
|
||||
return result;
|
||||
}
|
||||
|
||||
public MimClass createClass(final String name) {
|
||||
MimClass result = new MimClass();
|
||||
result.setName(name);
|
||||
result.setNamingStrategy(this);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameName(final String firstName, final String secondName) {
|
||||
return StringUtils.equalsIgnoreCase(firstName, secondName);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package ch.bitwave.mim.m2.core;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class ClassifierTest {
|
||||
@Test
|
||||
public void shouldGeneralize() {
|
||||
// Set up two classes with a specialization. A Car is a Vehicle.
|
||||
MimClass vehicleClass = new MimClass();
|
||||
vehicleClass.setName("Vehicle");
|
||||
MimClass carClass = new MimClass();
|
||||
carClass.setName("Car");
|
||||
Generalization gen = new Generalization();
|
||||
gen.setGeneral(vehicleClass);
|
||||
gen.setSpecific(carClass);
|
||||
// Now check the various methods related to generalizations.
|
||||
assertTrue(carClass.isSpecializationOf(vehicleClass));
|
||||
assertTrue(vehicleClass.isGeneralizationOf(carClass));
|
||||
assertFalse(carClass.isGeneralizationOf(vehicleClass));
|
||||
assertFalse(vehicleClass.isSpecializationOf(carClass));
|
||||
assertFalse(carClass.getSpecifics().contains(vehicleClass));
|
||||
assertFalse(vehicleClass.getGenerals().contains(carClass));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package ch.bitwave.mim.m2.profiles;
|
||||
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import ch.bitwave.mim.m2.core.MimClass;
|
||||
import ch.bitwave.mim.m2.core.MimPackage;
|
||||
|
||||
public class DelphiProfileTest {
|
||||
@Test
|
||||
public void shouldThreadIdentifiersCaseInsensitively() {
|
||||
DelphiProfile profile = new DelphiProfile();
|
||||
MimPackage toolbox = profile.createPackage("toolbox");
|
||||
MimClass utils = profile.createClass("utils");
|
||||
toolbox.addOwnedMember(utils);
|
||||
assertSame(utils, toolbox.findMember("Utils"));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue