public AssociationInfo isAssocClass() { // Only retrieve/compute the association once // Cache the result for subsequent use if (!isAssocClassAccessed) { isAssocClassAccessed = true; if (eaClassElement.GetSubtype() == 17 && !eaClassElement.MiscData(3).isEmpty()) { assoc = document.fAssociationById.get(eaClassElement.MiscData(3)); } } return assoc; }
// Validate tagged values cache, filtering on tagged values defined within // ShapeChange ... public void validateTaggedValuesCache() { if (taggedValuesCache == null) { // Fetch tagged values collection Collection<TaggedValue> tvs = eaClassElement.GetTaggedValues(); // ensure that there are tagged values if (tvs != null) { // Allocate cache int ntvs = tvs.GetCount(); taggedValuesCache = options().taggedValueFactory(ntvs); // Copy tag-value-pairs, leave out non-ShapeChange stuff and // normalize deprecated tags. for (TaggedValue tv : tvs) { String t = tv.GetName(); t = document.normalizeTaggedValue(t); if (t != null) { String v = tv.GetValue(); if (v.equals("<memo>")) v = tv.GetNotes(); taggedValuesCache.add(t, v); } } } else { taggedValuesCache = options().taggedValueFactory(0); } } } // validateTaggedValuesCache()
/** * Return the documentation attached to the property object. This is fetched from tagged values * and - if this is absent - from the 'notes' specific to the EA objects model. */ @Override public String documentation() { // Retrieve/compute the documentation only once // Cache the result for subsequent use if (!documentationAccessed) { documentationAccessed = true; // Try default first String s = super.documentation(); // Try EA notes, if both tagged values fail and ea:notes is the source if ((s == null || s.length() == 0) && descriptorSource(Options.Descriptor.DOCUMENTATION.toString()).equals("ea:notes")) { s = eaClassElement.GetNotes(); // Fix for EA7.5 bug if (s != null) { s = EADocument.removeSpuriousEA75EntitiesFromStrings(s); super.documentation = options().internalize(s); } } // If result is empty, check if we can get the documentation from a // dependency if (s == null || s.isEmpty()) { for (Iterator<String> i = this.supplierIds().iterator(); i.hasNext(); ) { String cid = i.next(); ClassInfoEA cix = document.fClassById.get(cid); if (cix != null) { if (cix.name().equalsIgnoreCase(this.name()) && cix.stereotype("featureconcept")) { s = cix.documentation(); break; } } } } // If result is empty, check if we can get the documentation from a // supertype with the same name (added for ELF/INSPIRE) if (s == null || s.isEmpty()) { HashSet<ClassInfoEA> sts = supertypesAsClassInfoEA(); if (sts != null) { for (ClassInfoEA stci : sts) { if (stci.name().equals(this.name())) { s = stci.documentation(); break; } } } } // Assign what we got or "" ... super.documentation = options().internalize(s != null ? s : ""); } return super.documentation; } // documentation()
/** @return set of ids of classes this class depends on */ protected TreeSet<String> supplierIds() { // Only retrieve/compute supplierIds once // Cache the results for subsequent use if (supplierIds == null) { // Prepare set to return supplierIds = new TreeSet<String>(); // Ask EA for the connectors attached to the package object and loop // over the connectors returned // Only compute them once for the whole class if (!connectorsAccessed) { conns = eaClassElement.GetConnectors(); connectorsAccessed = true; } // Ensure that there are connectors before continuing if (conns != null) { for (Connector conn : conns) { // Single out dependency connectors String type = conn.GetType(); if (type.equals("Dependency")) { // From the dependency grab the id of the supplier int suppId = conn.GetSupplierID(); String suppIdS = Integer.toString(suppId); // Since all connectors are delivered from both objects // at the // connector ends, we have to make sure it is not // accidently us, // which we found. if (suppId == eaClassId) continue; // Now, this is an element id, not a package id. So we // have to // identify the package, which owns the element // addressed. ClassInfoEA suppClass = (ClassInfoEA) document.fClassById.get(suppIdS); if (suppClass != null) { // From this only the id is required String suppPackId = suppClass.id(); if (suppPackId != null) supplierIds.add(suppPackId); } else { // package of supplier class has not been loaded, // dismiss the supplier } } } } } return supplierIds; } // supplierIds()
/** Set the tagged value for the tag given. */ public void taggedValue(String tag, String value) { Collection<TaggedValue> cTV = eaClassElement.GetTaggedValues(); TaggedValue tv = cTV.GetByName(tag); if (tv == null && value != null) { tv = cTV.AddNew(tag, value); tv.Update(); } else if (tv != null) { if (value == null) value = ""; if (!tv.GetValue().equals(value)) { tv.SetValue(value); tv.Update(); } } // invalidate cache taggedValuesCache = null; } // taggedValue()
// Validate stereotypes cache of the class. The stereotypes found are 1. // restricted to those defined within ShapeChange and 2. deprecated ones // are normalized to the lastest definitions. public void validateStereotypesCache() { if (stereotypesCache == null) { // Fetch stereotypes 'collection' ... String sts = eaClassElement.GetStereotypeEx(); String[] stereotypes = sts.split("\\,"); // Allocate cache stereotypesCache = options().stereotypesFactory(); // Copy stereotypes found in class selecting those defined in // ShapeChange and normalizing deprecated ones. for (String stereotype : stereotypes) { String st = document.options.normalizeStereotype(stereotype.trim()); if (st != null) for (String s : Options.classStereotypes) { if (st.toLowerCase().equals(s)) stereotypesCache.add(s); } } } } // validateStereotypesCache()
/** Get alias name of the class. */ @Override public String aliasName() { // Only retrieve/compute the alias once // Cache the result for subsequent use if (!aliasAccessed) { aliasAccessed = true; // Obtain alias name from default implementation String a = super.aliasName(); // If not present, obtain from EA model directly, if ea:alias is identified as the source if ((a == null || a.length() == 0) && descriptorSource(Options.Descriptor.ALIAS.toString()).equals("ea:alias")) { a = eaClassElement.GetAlias(); super.aliasName = options().internalize(a); } } return super.aliasName; } // aliasName()
// Validate operations cache. This makes sure the operations cache contains // all Operations ordered by their appearance in the class. private void validateOperationsCache() { if (operationsCache == null) { // Allocate the cache operationsCache = new TreeMap<Integer, OperationInfo>(); // Load methods ... Collection<Method> meths = eaClassElement.GetMethods(); int i = 0; // Ensure that there are methods before continuing if (meths != null) { for (Method meth : meths) { // Create the operation object. OperationInfoEA oi = new OperationInfoEA(document, this, meth); // Drop in cache // operationsCache.put(oi.eaMethod.GetPos(), oi); <-- does // not work! operationsCache.put(++i, oi); } } } } // validateOperationsCache()
// Establish all class associations. This is an auxiliary initializing // method, which retrieves all associations (EA: Connectors) known to // the class and creates wrapper objects for them in case they have not // already been encountered from the other class end. All created // association objects are registered. Object creation established the // necessary links to source and target objects and properties. // Note that invocation of this method requires that all classes of the // model are already cached. public void establishAssociations() { // Find out about associations connected to the class // Only do this once; cache the results for subsequent use if (!connectorsAccessed) { conns = eaClassElement.GetConnectors(); connectorsAccessed = true; } // check that this class has connectors if (conns != null) { // Enumerate connectors boolean known; int id; String connid; for (Connector conn : conns) { // only process "Association" connectors String type = conn.GetType(); if (!type.equalsIgnoreCase("Association") && !type.equalsIgnoreCase("Aggregation")) { continue; } // First find out whether the association has already been // processed from its other end. If so, discard. id = conn.GetConnectorID(); connid = new Integer(id).toString(); known = document.fAssociationById.containsKey(connid); if (known) continue; // First encounter: Create AssociationInfo wrapper and // properties linkage. AssociationInfoEA ai = new AssociationInfoEA(document, conn, id); // Register with global associations map, if relevant class // association if (ai.relevant) document.fAssociationById.put(connid, ai); } } }
/** * Create new ClassInfo object * * @throws ShapeChangeAbortException */ public ClassInfoEA(EADocument doc, PackageInfoEA pi, org.sparx.Element elmt) throws ShapeChangeAbortException { // Memorize document and parent package. document = doc; packageInfo = pi; // EA object reference. Fetch id and name. eaClassElement = elmt; eaClassId = eaClassElement.GetElementID(); eaName = eaClassElement.GetName().trim(); // Register as child of parent package. pi.childCI.add(this); if (options().isLoadGlobalIdentifiers()) { globalIdentifier = document.repository.GetProjectInterface().GUIDtoXML(eaClassElement.GetElementGUID()); } // Determine some class flags isAbstract = eaClassElement.GetAbstract().equals("1"); isLeaf = eaClassElement.GetIsLeaf(); // Determine class category if (elmt.GetType().equalsIgnoreCase("enumeration")) category = Options.ENUMERATION; else establishCategory(); // Cache if realisations should not be treated as generalisations /* * 2015-04-16 JE TBD: 'realisationLikeGeneralisation' should become a * general input parameter. Loading of the input model should not depend * on a specific target. */ String realization = document.options.parameter(Options.TargetXmlSchemaClass, "realisationLikeGeneralisation"); if (realization != null && realization.equalsIgnoreCase("false")) { this.realization = Boolean.FALSE; } } // ClassInfoEA Ctor
// Validate properties cache. This makes sure the property cache contains // all properties ordered by their appearance in the class. private void validatePropertiesCache() { if (propertiesCache == null) { // Allocate the cache propertiesCache = new TreeMap<StructuredNumber, PropertyInfo>(); // Load attributes ... Collection<Attribute> attrs = eaClassElement.GetAttributes(); // Ensure that there are attributes before continuing if (attrs != null) { for (Attribute attr : attrs) { // Pick public attributes if this has been requested if (document.options.parameter("publicOnly").equals("true")) { String vis = attr.GetVisibility(); if (!vis.equalsIgnoreCase("Public")) { continue; } } // Create the property object. PropertyInfoEA pi = new PropertyInfoEA(document, this, attr); // Check sequence number on duplicates PropertyInfo piTemp = propertiesCache.get(pi.sequenceNumber()); if (piTemp != null) { int cat = category(); if (cat != Options.ENUMERATION && cat != Options.CODELIST && !pi.sequenceNumber.equals(new StructuredNumber(Integer.MIN_VALUE))) { MessageContext mc = document.result.addError(null, 107, pi.name(), name(), piTemp.name()); if (mc != null) mc.addDetail(null, 400, "Package", pkg().fullName()); } } // Add to properties cache propertiesCache.put(pi.sequenceNumber(), pi); } } // Load roles ... for (PropertyInfoEA pi : registeredRoles) { // Check sequence number on duplicates PropertyInfo piTemp = propertiesCache.get(pi.sequenceNumber()); if (piTemp != null) { MessageContext mc = document.result.addError(null, 107, pi.name(), name(), piTemp.name()); if (mc != null) mc.addDetail(null, 400, "Package", pkg().fullName()); } // Add to properties cache propertiesCache.put(pi.sequenceNumber(), pi); } // Are there any nilReason implementation uses in the class ? // This is called at the end of loading all properties, // as there could be cases in which the order of the property // loading // matters, for example the detection of the union direct case // in the implementedByNilReason() method. for (PropertyInfo pi : propertiesCache.values()) { if (pi.implementedByNilReason()) hasNilReason = true; } } } // validatePropertiesCache()
// Validate constraints cache. This makes sure the constraints cache // contains all constraints ordered by their appearance in the class. // If constraints are disabled the cache is empty. private void validateConstraintsCache() { if (constraintsCache == null) { // Allocate cache constraintsCache = new Vector<Constraint>(); // Constraints disabled? String check = document.options.parameter("checkingConstraints"); if (check != null && check.equalsIgnoreCase("disabled")) return; // Constraints for this class category irrelevant? if (!document.options.isClassTypeToCreateConstraintsFor(category())) return; // Constraints from selected schemas only? if (document.options.isLoadConstraintsForSelectedSchemasOnly() && !document.isInSelectedSchemas(this)) { return; } // Filter map for inheritance and overriding by name HashMap<String, Constraint> namefilter = new HashMap<String, Constraint>(); // Access EA constraints data Collection<org.sparx.Constraint> constrs = eaClassElement.GetConstraints(); // Determine constraint types to be parsed as OCL String oclTypes = document.options.parameter("oclConstraintTypeRegex"); // Determine constraint types to be parsed as FOL String folTypes = document.options.parameter("folConstraintTypeRegex"); // Enumerate all constraints found // Ensure that there are constraints before continuing if (constrs != null) { for (org.sparx.Constraint constr : constrs) { // Wrap into constraint object String type = constr.GetType(); Constraint oc; if (oclTypes.length() > 0 && type.matches(oclTypes)) { // 100422/re removed: && // !encodingRule("xsd").equals(Options.ISO19136_2007_INSPIRE) OclConstraintEA ocl = new OclConstraintEA(document, this, constr); if (ocl.syntaxTree() == null) // Text constraint is a fallback in case of parsing // issues oc = new TextConstraintEA(document, this, constr); else oc = ocl; } else if (folTypes != null && folTypes.length() > 0 && type.matches(folTypes)) { /* * only sets up the textual information; parsing is done * during model postprocessing - see * ModelImpl.postprocessFolConstraints() */ oc = new FolConstraintEA(document, this, constr); } else { oc = new TextConstraintEA(document, this, constr); } // Collect in cache constraintsCache.add(oc); // If the constraint has a name, add it to the filter which // blocks inheritance of constraints String conam = oc.name(); if (conam != null && conam.length() > 0) namefilter.put(conam, oc); } } /* * Fetch constraints from super-classes. Override by name. */ /* * JE: replaced this code with code (see below) that directly * accesses the supertype objects, instead of first getting all * their IDs and then looking the objects up in the model. */ // HashSet<String> stids = supertypes(); // if (stids != null) { // for (String stid : stids) { // ClassInfo stci = model().classById(stid); // Vector<Constraint> stcos = null; // if (stci != null) // stcos = stci.constraints(); // if (stcos != null) { // for (Constraint stco : stcos) { // String nam = stco == null ? null : stco.name(); // if(nam!=null && nam.length()>0 && namefilter.containsKey(nam)) // continue; // constraintsCache.add(stco); // } // } // } // } HashSet<ClassInfoEA> sts = supertypesAsClassInfoEA(); if (sts != null) { for (ClassInfoEA stci : sts) { Vector<Constraint> stcos = null; if (stci != null) stcos = stci.constraints(); if (stcos != null) { for (Constraint stco : stcos) { String nam = stco == null ? null : stco.name(); if (nam != null && nam.length() > 0 && namefilter.containsKey(nam)) continue; // Is the context of stco still the supertype, or // should it not be this (ClassInfoEA)? constraintsCache.add(stco); } } } } } }
// Establish class derivation hierarchy. This auxiliary initializing // method sets the base class relation ship obtained from the model and // also enters this class as subclass of all its base classes. // Note that invocation of this method requires that all classes in // the model are already cached. // Note: ISO19107 makes use of realization instead of generalization in some // cases to inherit from interfaces. Therefore realization of interfaces is // also considered a base class relationship as a default unless overruled // by // a parameter. public void establishClassDerivationHierarchy() { // Find out about all connectors attached to the class // Only do this once; cache the results for subsequent use if (!connectorsAccessed) { conns = eaClassElement.GetConnectors(); connectorsAccessed = true; } // check that this class has connectors if (conns != null) { // Enumerate connectors selecting those where this class is the // client, // from these select "Generalization" and "Realisation". Retrieve // the // supplier class wrappers. For "Realisation" type suppliers also // make // sure the class is an interface. The classes found are registered // as // base classes. In the base classes register this class as // subclass. int nbcl = 0; int clientid, bclid, cat; String conntype; boolean gen, rea; for (Connector conn : conns) { // Skip all other connector types conntype = conn.GetType(); gen = conntype.equals("Generalization"); rea = conntype.equals("Realisation"); // this.realization is determined from configuration parameters // if it is not null then it is false if (this.realization != null && !this.realization.booleanValue()) rea = false; if (!gen && !rea) continue; // Make sure we are the client of this connector clientid = conn.GetClientID(); if (clientid != this.eaClassId) continue; // Find out about the id of the base class (=supplier) bclid = conn.GetSupplierID(); // From this determine the ClassInfo wrapper object ClassInfoEA baseCI = document.fClassById.get(String.valueOf(bclid)); // If such an object exists establish it as base class. if (baseCI != null) { // If we know this via a Realization we additionally check // we are seeing an interface. if (rea) { cat = baseCI.category(); if (cat != Options.MIXIN) continue; } // Establish as base class. Since most classes indeed // possess // at most one base class, this case will be treated // somewhat // storage-optimized. if (++nbcl == 1) { baseclassInfo = baseCI; } else { if (baseclassInfoSet == null) { baseclassInfoSet = new TreeSet<ClassInfoEA>(); baseclassInfoSet.add(baseclassInfo); baseclassInfo = null; } baseclassInfoSet.add(baseCI); } // Register with the subclasses of the base class. baseCI.subclassInfoSet.add(this); } } } } // establishClassDerivationHierarchy()