All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.modeldriven.fuml.repository.model.Property Maven / Gradle / Ivy

Go to download

This open source software is a reference implementation, consisting of software and related files, for the OMG specification called the Semantics of a Foundational Subset for Executable UML Models (fUML). The reference implementation is intended to implement the execution semantics of UML activity models, accepting an XMI file from a conformant UML model as its input and providing an execution trace of the selected activity model(s) as its output. The core execution engine, which is directly generated from the normative syntactic and semantic models for fUML, may also be used as a library implementation of fUML in other software.

There is a newer version: 1.5.0a
Show newest version
package org.modeldriven.fuml.repository.model;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.modeldriven.fuml.assembly.AssemblyException;
import org.modeldriven.fuml.environment.Environment;
import org.modeldriven.fuml.io.ArtifactLoader;
import org.modeldriven.fuml.repository.Element;
import org.modeldriven.fuml.repository.Class_;
import org.modeldriven.fuml.repository.Classifier;
import org.modeldriven.fuml.repository.Repository;
import org.modeldriven.fuml.repository.RepositoryArtifact;
import org.modeldriven.fuml.repository.RepositoryException;
import org.modeldriven.fuml.xmi.InvalidReferenceException;

import UMLPrimitiveTypes.UnlimitedNatural;
import fuml.syntax.classification.InstanceValue;
import fuml.syntax.simpleclassifiers.EnumerationLiteral;
import fuml.syntax.structuredclassifiers.Association;
import fuml.syntax.values.LiteralBoolean;
import fuml.syntax.values.LiteralInteger;
import fuml.syntax.values.LiteralNull;
import fuml.syntax.values.LiteralString;
import fuml.syntax.values.LiteralUnlimitedNatural;
import fuml.syntax.values.ValueSpecification;

public class Property extends NamedElement 
    implements org.modeldriven.fuml.repository.Property{


    private static Log log = LogFactory.getLog(Property.class);
	private fuml.syntax.classification.Property property;
	    
    public Property(fuml.syntax.classification.Property property,
    		RepositoryArtifact artifact) {
    	super(property, artifact);
    	this.property = property;
    }
	
    public Class_ getClass_() {
    	return (Class_)Repository.INSTANCE.getElementById(this.property.class_.getXmiId());
    }
	
	public ValueSpecification getDefaultValue() {
		return this.property.defaultValue;
	}

	public void setDefaultValue(ValueSpecification defaultValue) {
		this.property.defaultValue = defaultValue;
	}

	public org.modeldriven.fuml.repository.Property getOpposite() {
		if (this.property.opposite != null)
		{	
			org.modeldriven.fuml.repository.Property result = (org.modeldriven.fuml.repository.Property)Repository.INSTANCE.getElementById(this.property.opposite.getXmiId());
		    return result;
		}
		
		if (property.owningAssociation == null) {
			fuml.syntax.classification.Property otherEnd = getOtherEnd(this);

			if (otherEnd != null && otherEnd.owningAssociation == null) {
				this.property.opposite = otherEnd;
				org.modeldriven.fuml.repository.Property result = (org.modeldriven.fuml.repository.Property)Repository.INSTANCE.getElementById(this.property.opposite.getXmiId());
			    return result;
			}
		}
		return null;
	}
	
	public fuml.syntax.classification.Property getDelegate() {
		return this.property;
	}

    public Classifier getType() {
    	return this.findType(false);
    }
	
    public Classifier findType() {
    	return this.findType(true);
    }   
    
    private Classifier findType(boolean supressErrors) {
        Classifier result = null;
        
        if (this.property.typedElement != null && this.property.typedElement.type != null)
        {
	        String typeXmiId = this.property.typedElement.type.getXmiId();
	        if (typeXmiId != null) {
	        	Element elementResult = Repository.INSTANCE.getElementById(typeXmiId);
	        	try {
	        	    result = (Classifier)elementResult;
	        	}
	        	catch (ClassCastException e) {
	        		throw new RuntimeException(e);
	        	}
	        	//if (Classifier.class.isAssignableFrom(Element.class))
	        	//    result = Classifier.class.cast(elementResult);
	            //else
	            //	throw new IllegalStateException(Classifier.class.getName() 
	            //		+ " cannot be assigned from " + Element.class.getName());
	            if (result == null && !supressErrors)
	                throw new InvalidReferenceException(typeXmiId);
	        }
        }
        if (result == null && !supressErrors)
            throw new RepositoryException("no type found for property, " 
            		+ this.property.class_.name + "." + this.property.name);
        return result;
    }
    
    public boolean isDataType() {
    	return getType().isDataType();
    }
    
    public Association getAssociation() {
    	return this.property.association;
    }
    
    public void setAssociation(Association assoc) {
    	this.property.association = assoc;
    }
    
    public boolean isDerived() {
    	return this.property.isDerived;
    }
    
    public boolean isRequired() {
        return this.getLowerValue() > 0;
    }

    public boolean isSingular() {
        return "1".equals(this.getUpperValue());
    }
    
    public String getPropertyDefault() {
        return getPropertyDefaultValue(false);
    }

    public String findPropertyDefault() {
        return getPropertyDefaultValue(true);
    }

    public boolean hasPropertyDefaultValue() {
        String value = getPropertyDefaultValue(true);
        return value != null && value.trim().length() > 0;
    }

    private String getPropertyDefaultValue(boolean supressErrors) {
        ValueSpecification valueSpec = findDefaultValueSpecification();
        if (valueSpec != null)
            return getValue(valueSpec);
        else
            return null;
    }

    private ValueSpecification findDefaultValueSpecification() {
        return property.defaultValue;
    }
    
    public String getUpperValue() {
        return getValue(this.property.multiplicityElement.upperValue);
    }

    public int getLowerValue() {
    	String value = getValue(this.property.multiplicityElement.lowerValue);
         if (value == null || "null".equalsIgnoreCase(value))
            value = "0";
        return Integer.valueOf(value);
    }

    private String getValue(ValueSpecification valueSpec) {
        if (LiteralString.class.isAssignableFrom(valueSpec.getClass())) {
            return ((LiteralString)valueSpec).value;
        }
        else if (LiteralInteger.class.isAssignableFrom(valueSpec.getClass())) {
            return String.valueOf(((LiteralInteger)valueSpec).value); // use specifically typed value in subclass
        }
        else if (LiteralBoolean.class.isAssignableFrom(valueSpec.getClass())) {
            return String.valueOf(((LiteralBoolean)valueSpec).value); // use specifically typed value in subclass
        }
        else if (LiteralNull.class.isAssignableFrom(valueSpec.getClass())) {
            return null;
        }
        else if (LiteralUnlimitedNatural.class.isAssignableFrom(valueSpec.getClass())) {
            return String.valueOf(((LiteralUnlimitedNatural)valueSpec).value.naturalValue);
        } else if (InstanceValue.class.isAssignableFrom(valueSpec.getClass())) {
        	InstanceValue instanceValue = (InstanceValue)valueSpec;
        	if (EnumerationLiteral.class.isAssignableFrom(instanceValue.instance.getClass()))
        	{
        		EnumerationLiteral enumerationLiteral = (EnumerationLiteral)instanceValue.instance;
        		return enumerationLiteral.name;
        	}
        	else
                throw new RepositoryException("unknown instance type, " 
                		+ instanceValue.instance.getClass().getName());
        } else {
            // return ((OpaqueExpression)valueSpec).getBody();
            throw new IllegalArgumentException("expected literal or instance value");
        }
    }

    private void setValue(ValueSpecification valueSpec, String value) {
        if (LiteralString.class.isAssignableFrom(valueSpec.getClass()))
        	((LiteralString)valueSpec).value = value;
        else if (LiteralInteger.class.isAssignableFrom(valueSpec.getClass()))
        	((LiteralInteger)valueSpec).value = Integer.parseInt(value);
        else if (LiteralBoolean.class.isAssignableFrom(valueSpec.getClass()))
            ((LiteralBoolean)valueSpec).value = Boolean.parseBoolean(value);
        //else if (LiteralNull.class.isAssignableFrom(valueSpec.getClass()))        	 	
        else if (LiteralUnlimitedNatural.class.isAssignableFrom(valueSpec.getClass())) {
        	UnlimitedNatural un = new UnlimitedNatural();
        	un.naturalValue = Integer.parseInt(value);
        	((LiteralUnlimitedNatural)valueSpec).value = un;
        } else if (InstanceValue.class.isAssignableFrom(valueSpec.getClass())) {
            valueSpec.setName(value);
        } else {
            // ((OpaqueExpression)valueSpec).setBody(value);
            throw new IllegalArgumentException("expected literal or instance value");
        }
    }
    
	private static fuml.syntax.classification.Property getOtherEnd(org.modeldriven.fuml.repository.Property property) {
		Association association = property.getAssociation();

		if (association != null) {
			List memberEnds = association.memberEnd;

			if (memberEnds.size() == 2) {
				int index = memberEnds.indexOf(property.getDelegate());

				if (index != -1) {
					return (fuml.syntax.classification.Property) memberEnds.get(Math.abs(index - 1));
				}
			}
			else if (log.isDebugEnabled())
				log.debug("expected exactly 2 (not " 
						+ memberEnds.size() + ") member-end elements for association ("
						+ association.getXmiId() + ") linking property " 
						+ property.getClass_().getQualifiedName() + "." + property.getName()
						+ " - ignoring any association owned-end property as not applicable as property opposite");
			// Note where one end (Property) of an association is linked to a read-only class, tools (MagicDraw)
			// will necessarily create an association owned-end as it cannot modify the target read-only class. This
			// can be the case when imported read-only modules are used.
		}

		return null;
	}
	
} // Property




© 2015 - 2025 Weber Informatics LLC | Privacy Policy