/// <summary> /// Updated the energistics model (common and resqml model) according to the input fesapi model. /// </summary> public void updateEnergisticsModel() { // looking for: // - fesapi classes that exists in the energistics model (according to their name). For // that purpose, toUpdateClassF2E makes a correspondance between a fesapi class (key) and // corresponding Energistics class (value). These classes will then be updated into // the energistics model // - fesapi classes that does not exist in the Energistics model. These classes are collected // into toAddClassList. These classes will then be added to the Energistics model Dictionary <EA.Element, EA.Element> toUpdateClassF2E = new Dictionary <EA.Element, EA.Element>(); List <EA.Element> toAddClassList = new List <EA.Element>(); foreach (EA.Element fesapiClass in fesapiClassList) { EA.Element energisticsClass = energisticsClassList.Find(c => c.Name.Equals(fesapiClass.Name)); if (energisticsClass != null) { toUpdateClassF2E.Add(fesapiClass, energisticsClass); } else { toAddClassList.Add(fesapiClass); } } // console output Tool.log(repository, "classes to update:"); foreach (KeyValuePair <EA.Element, EA.Element> entry in toUpdateClassF2E) { Tool.log(repository, " " + entry.Value.Name); } Tool.log(repository, "classes to add:"); foreach (EA.Element c in toAddClassList) { Tool.log(repository, " " + c.Name); } // handling classes that exist into the Energistics model foreach (KeyValuePair <EA.Element, EA.Element> entry in toUpdateClassF2E) { EA.Element fesapiClass = entry.Key; EA.Element energisticsClass = entry.Value; // adding a fesapiGeneration tag to true EA.TaggedValue t = energisticsClass.TaggedValues.AddNew(Constants.fesapiGenerationTagName, "true"); if (!(t.Update())) { Tool.showMessageBox(repository, t.GetLastError()); continue; } energisticsClass.TaggedValues.Refresh(); // adding a fesapiNamespace tag. The tag value is set to the name of // package containing the fesapi class. This tag will be used to determine: // - the name space of the generated class // - the output directory of the generated class EA.Package p = repository.GetPackageByID(fesapiClass.PackageID); t = energisticsClass.TaggedValues.AddNew(Constants.fesapiNamespaceTagName, p.Name); if (!(t.Update())) { Tool.showMessageBox(repository, t.GetLastError()); continue; } energisticsClass.TaggedValues.Refresh(); // updating the ENergistics class according to the corresponding // fesapi class updateEnergisticsClass(energisticsClass, fesapiClass); } // handling classes that does not exist into the Energistics model foreach (EA.Element c in toAddClassList) { // getting the package carrying the fesapi class EA.Package sourcePackagePackage = repository.GetPackageByID(c.PackageID); // getting the package where to create the corresponding Energistics class EA.Package targetPackage = null; if (sourcePackagePackage.Name.Contains("common")) { targetPackage = Tool.getOrCreatePackage(repository, commonModel, "fesapi"); } else if (sourcePackagePackage.Name.Contains("resqml")) { targetPackage = Tool.getOrCreatePackage(repository, resqmlModel, "fesapi"); } if (targetPackage == null) { Tool.showMessageBox(repository, "The fesapi class " + c.Name + " is not handled. It will be skipped!"); continue; } // creating the new class EA.Element newClass = Tool.copyElement(repository, c, targetPackage); if (newClass == null) { Tool.showMessageBox(repository, "Not able to create a " + c.Name + " class in the Energistics model"); continue; } // adding a fesapiGeneration tag to true EA.TaggedValue t = newClass.TaggedValues.AddNew(Constants.fesapiGenerationTagName, "true"); if (!(t.Update())) { Tool.showMessageBox(repository, t.GetLastError()); continue; } newClass.TaggedValues.Refresh(); // adding a fesapiNamespace tag. The tag value is set to the name of // package containing the fesapi class. This tag will be used to determine: // - the name space of the generated class // - the output directory of the generated class t = newClass.TaggedValues.AddNew(Constants.fesapiNamespaceTagName, sourcePackagePackage.Name); if (!(t.Update())) { Tool.showMessageBox(repository, t.GetLastError()); continue; } newClass.TaggedValues.Refresh(); } // looking in the Energistics common model for a newly created EpcDocument class // if such class exists, we create its easy access vector members EA.Package commonFesapiPackage; try { commonFesapiPackage = commonModel.Packages.GetByName("fesapi"); } catch (Exception) { commonFesapiPackage = null; } if (commonFesapiPackage != null) { EA.Element epcDocumentClass = commonFesapiPackage.Elements.GetByName("EpcDocument"); if (epcDocumentClass != null) { createEpcDocumentEasyAccessVector(epcDocumentClass, toUpdateClassF2E); } } // make sure the model view is up to date in the Enterprise Architect GUI repository.RefreshModelView(0); }
/// <summary> /// This method basically copy the content of a fesapi class into an Energistics class. /// Attributes, methods, tags and notes are handled. /// Important notes: /// - common attributes and tags (according to their name) existing content will be erased /// - existing notes will be erased during this process /// </summary> /// <param name="fesapiClass">A source fesapi class</param> /// <param name="energisticsClass">A target Energistics class</param> private void copyClassContent(EA.Element fesapiClass, EA.Element energisticsClass) { // ------------------- // ------------------- // attributes handling // for each fesapi attribute, if a corresponding Energistics attritute exists // (that is to say if the Energistics class contains an attribute with the same name) // we copy the fesapi attribute content into the Energistics attribute content else we create from scratch // an Energistics attribute foreach (EA.Attribute fesapiAttribute in fesapiClass.Attributes) { EA.Attribute correspondingEnergisticsAttribute = null; foreach (EA.Attribute a in energisticsClass.Attributes) { if (a.Name == fesapiAttribute.Name) { correspondingEnergisticsAttribute = a; break; } } // if there is no corresponding target attribute, we create one if (correspondingEnergisticsAttribute == null) { correspondingEnergisticsAttribute = energisticsClass.Attributes.AddNew(fesapiAttribute.Name, fesapiAttribute.Type); if (!(correspondingEnergisticsAttribute.Update())) { Tool.showMessageBox(repository, correspondingEnergisticsAttribute.GetLastError()); continue; } energisticsClass.Attributes.Refresh(); } correspondingEnergisticsAttribute.Alias = fesapiAttribute.Alias; correspondingEnergisticsAttribute.AllowDuplicates = fesapiAttribute.AllowDuplicates; correspondingEnergisticsAttribute.ClassifierID = fesapiAttribute.ClassifierID; correspondingEnergisticsAttribute.Container = fesapiAttribute.Container; correspondingEnergisticsAttribute.Containment = fesapiAttribute.Containment; correspondingEnergisticsAttribute.Default = fesapiAttribute.Default; correspondingEnergisticsAttribute.IsCollection = fesapiAttribute.IsCollection; correspondingEnergisticsAttribute.IsConst = fesapiAttribute.IsConst; correspondingEnergisticsAttribute.IsDerived = fesapiAttribute.IsDerived; correspondingEnergisticsAttribute.IsID = fesapiAttribute.IsID; correspondingEnergisticsAttribute.IsOrdered = fesapiAttribute.IsOrdered; correspondingEnergisticsAttribute.IsStatic = fesapiAttribute.IsStatic; correspondingEnergisticsAttribute.Length = fesapiAttribute.Length; correspondingEnergisticsAttribute.LowerBound = fesapiAttribute.LowerBound; correspondingEnergisticsAttribute.Notes = fesapiAttribute.Notes; correspondingEnergisticsAttribute.Precision = fesapiAttribute.Precision; correspondingEnergisticsAttribute.RedefinedProperty = fesapiAttribute.RedefinedProperty; correspondingEnergisticsAttribute.Scale = fesapiAttribute.Scale; correspondingEnergisticsAttribute.Stereotype = fesapiAttribute.Stereotype; correspondingEnergisticsAttribute.StereotypeEx = fesapiAttribute.StereotypeEx; correspondingEnergisticsAttribute.Style = fesapiAttribute.Style; correspondingEnergisticsAttribute.StyleEx = fesapiAttribute.StyleEx; correspondingEnergisticsAttribute.SubsettedProperty = fesapiAttribute.SubsettedProperty; correspondingEnergisticsAttribute.Type = fesapiAttribute.Type; correspondingEnergisticsAttribute.UpperBound = fesapiAttribute.UpperBound; correspondingEnergisticsAttribute.Visibility = fesapiAttribute.Visibility; if (!(correspondingEnergisticsAttribute.Update())) { Tool.showMessageBox(repository, correspondingEnergisticsAttribute.GetLastError()); continue; } foreach (EA.AttributeTag fesapiAttributeTag in fesapiAttribute.TaggedValues) { EA.AttributeTag energisticsAttributeTag = correspondingEnergisticsAttribute.TaggedValues.AddNew(fesapiAttributeTag.Name, fesapiAttributeTag.Value); if (!(energisticsAttributeTag.Update())) { Tool.showMessageBox(repository, energisticsAttributeTag.GetLastError()); } } correspondingEnergisticsAttribute.TaggedValues.Refresh(); } // ---------------- // ---------------- // methods handling // we assume that the Energistics model does not contain methods. So, for each fesapi class method // a copy is created into the energistics class foreach (EA.Method fesapiMethod in fesapiClass.Methods) { EA.Method energisticsMethod = energisticsClass.Methods.AddNew(fesapiMethod.Name, fesapiMethod.ReturnType); energisticsMethod.Abstract = fesapiMethod.Abstract; energisticsMethod.Behavior = fesapiMethod.Behavior; energisticsMethod.ClassifierID = fesapiMethod.ClassifierID; energisticsMethod.Code = fesapiMethod.Code; energisticsMethod.Concurrency = fesapiMethod.Concurrency; energisticsMethod.IsConst = fesapiMethod.IsConst; energisticsMethod.IsLeaf = fesapiMethod.IsLeaf; energisticsMethod.IsPure = fesapiMethod.IsPure; energisticsMethod.IsQuery = fesapiMethod.IsQuery; energisticsMethod.IsRoot = fesapiMethod.IsRoot; energisticsMethod.IsStatic = fesapiMethod.IsStatic; energisticsMethod.IsSynchronized = fesapiMethod.IsSynchronized; energisticsMethod.Notes = fesapiMethod.Notes; energisticsMethod.ReturnIsArray = fesapiMethod.ReturnIsArray; energisticsMethod.StateFlags = fesapiMethod.StateFlags; energisticsMethod.Stereotype = fesapiMethod.Stereotype; energisticsMethod.StereotypeEx = fesapiMethod.StereotypeEx; energisticsMethod.Style = fesapiMethod.Style; energisticsMethod.StyleEx = fesapiMethod.StyleEx; energisticsMethod.Throws = fesapiMethod.Throws; energisticsMethod.Visibility = fesapiMethod.Visibility; if (!(energisticsMethod.Update())) { Tool.showMessageBox(repository, energisticsMethod.GetLastError()); } energisticsClass.Methods.Refresh(); foreach (EA.MethodTag fesapiMethodTag in fesapiMethod.TaggedValues) { EA.MethodTag energisticsMethodTag = energisticsMethod.TaggedValues.AddNew(fesapiMethodTag.Name, fesapiMethodTag.Value); if (!(energisticsMethodTag.Update())) { Tool.showMessageBox(repository, energisticsMethodTag.GetLastError()); } } energisticsMethod.TaggedValues.Refresh(); foreach (EA.Parameter fesapiMethodParameter in fesapiMethod.Parameters) { EA.Parameter energisticsMethodParameter = energisticsMethod.Parameters.AddNew(fesapiMethodParameter.Name, fesapiMethodParameter.Type); energisticsMethodParameter.Alias = fesapiMethodParameter.Alias; energisticsMethodParameter.ClassifierID = fesapiMethodParameter.ClassifierID; energisticsMethodParameter.Default = fesapiMethodParameter.Default; energisticsMethodParameter.IsConst = fesapiMethodParameter.IsConst; energisticsMethodParameter.Kind = fesapiMethodParameter.Kind; energisticsMethodParameter.Notes = fesapiMethodParameter.Notes; energisticsMethodParameter.Position = fesapiMethodParameter.Position; energisticsMethodParameter.Stereotype = fesapiMethodParameter.Stereotype; energisticsMethodParameter.StereotypeEx = fesapiMethodParameter.StereotypeEx; energisticsMethodParameter.Style = fesapiMethodParameter.Style; energisticsMethodParameter.StyleEx = fesapiMethodParameter.StyleEx; if (!(energisticsMethodParameter.Update())) { Tool.showMessageBox(repository, energisticsMethodParameter.GetLastError()); } } energisticsMethod.Parameters.Refresh(); } // ------------- // ------------- // tags handling foreach (EA.TaggedValue fesapiTag in fesapiClass.TaggedValues) { EA.TaggedValue energisticsTag = energisticsClass.TaggedValues.AddNew(fesapiTag.Name, fesapiTag.Value); if (!(energisticsTag.Update())) { Tool.showMessageBox(repository, energisticsTag.GetLastError()); } energisticsClass.TaggedValues.Refresh(); } // -------------- // -------------- // notes handling // important note: Energistics class notes are deleted during this copy if (fesapiClass.Notes != "") { energisticsClass.Notes = fesapiClass.Notes; if (!(energisticsClass.Update())) { Tool.showMessageBox(repository, energisticsClass.GetLastError()); } } energisticsClass.Refresh(); }
/// <summary> /// This methods create some easy access vector attributes into an Energistics EpcDocument /// class. These vector are usefull to access top level Resqml objects from one EpcDocument. /// It also provides corresponding accessors and forward declarations. /// </summary> /// <param name="energisticsEpcDocument">An Energistics EpcDocument class</param> /// <param name="toUpdateClassF2E">A dictionary mapping Fesapi classes with their corresponding Energistics classes</param> private void createEpcDocumentEasyAccessVector(EA.Element energisticsEpcDocument, Dictionary <EA.Element, EA.Element> toUpdateClassF2E) { // we create a dictionry for mapping a given fesapi namespace with corresponding fesapi class. // Usefull for handling EpcDocument forward declarations Dictionary <string, List <string> > importNamespace = new Dictionary <string, List <string> >(); foreach (KeyValuePair <EA.Element, EA.Element> entry in toUpdateClassF2E) { EA.Element energisticsClass = entry.Value; // we assume that we do not want to provide easy access vectors to access abstract classes from // EpcDocument if (energisticsClass.Name.Contains("Abstract")) { continue; } // getting the fesapi namespace of the current non-abstract Energistics class. It exists since // the EpcDocument easy access vectors creation occurs at the very end of the Energistics model // update EA.TaggedValue tag = energisticsClass.TaggedValues.GetByName(Constants.fesapiNamespaceTagName); // creating the EpcDocument std::vector attribute for easily access the current Energistics class string attributeName = Char.ToLowerInvariant(energisticsClass.Name[0]) + energisticsClass.Name.Substring(1) + "Set"; string attributeType = "std::vector<" + tag.Value + "::" + energisticsClass.Name + "*>"; EA.Attribute attribute = attribute = energisticsEpcDocument.Attributes.AddNew(attributeName, attributeType); attribute.Visibility = "Private"; if (!(attribute.Update())) { Tool.showMessageBox(repository, attribute.GetLastError()); continue; } energisticsEpcDocument.Attributes.Refresh(); // thanks to a tag, we tell to the transformation engine (transforming the Energistics model into a C++ model) // to preserve our easy access vector attribute in the C++ model EA.AttributeTag generationTag = attribute.TaggedValues.AddNew(Constants.fesapiGenerationTagName, "true"); if (!(generationTag.Update())) { Tool.showMessageBox(repository, generationTag.GetLastError()); continue; } attribute.TaggedValues.Refresh(); // we want to generate by hand the corresponding getter. Thanks to a tag, we tell to the model // transformation engine (transforming the Energistics model into a C++ model) to do not automatically // generate a getter EA.AttributeTag getterGenerationTag = attribute.TaggedValues.AddNew(Constants.fesapiGetterGenerationTagName, "false"); if (!(getterGenerationTag.Update())) { Tool.showMessageBox(repository, getterGenerationTag.GetLastError()); continue; } // we create by hand the corresponding vector string methodName = "get" + energisticsClass.Name + "Set"; string methodType = attributeType + " &"; EA.Method method = energisticsEpcDocument.Methods.AddNew(methodName, methodType); method.IsConst = true; method.Stereotype = "const"; if (!(method.Update())) { Tool.showMessageBox(repository, method.GetLastError()); continue; } energisticsEpcDocument.Methods.Refresh(); // associating the Energistics class to its fesapi namespace if (!(importNamespace.ContainsKey(tag.Value))) { importNamespace.Add(tag.Value, new List <string>()); } importNamespace[tag.Value].Add(energisticsClass.Name); } // converting the association between fesapi namespace and Energistics classes into a // EpcDocument class tag. This tag will be used during the code generation for copying // forward declarations corresponding to easy access vectors into EpcDocument.h string importNameSpaceTagValue = ""; foreach (KeyValuePair <string, List <string> > kv in importNamespace) { importNameSpaceTagValue += "namespace " + kv.Key + " {"; List <string> classNameList = kv.Value; foreach (string className in classNameList) { importNameSpaceTagValue += "class " + className + ";"; } importNameSpaceTagValue += "}"; } EA.TaggedValue importNamespaceTag = energisticsEpcDocument.TaggedValues.AddNew(Constants.fesapiImportNamespaceTag, importNameSpaceTagValue); if (!(importNamespaceTag.Update())) { Tool.showMessageBox(repository, importNamespaceTag.GetLastError()); } energisticsEpcDocument.TaggedValues.Refresh(); }
/// <summary> /// Add an XML_TAG attribute with its getter to a given Energistics class. This method /// has no effect if the Energistics class is abstract or if the corresponding fesapi class /// is tagged such that no XML_TAG should be generated /// </summary> /// <param name="energisticsClass">An Energistics class</param> /// <param name="fesapiClass">Its corresponding fesapi class</param> private void addXmlTagAttributeWithGetter(EA.Element energisticsClass, EA.Element fesapiClass) { // we look for a fesapi class tag telling that no XML_TAG attribute should be generated string generateXmlTag = "true"; EA.TaggedValue generateXmlTagTag = fesapiClass.TaggedValues.GetByName(Constants.fesapiGenerateXmlTagTagName); if (generateXmlTagTag != null) { generateXmlTag = generateXmlTagTag.Value; } if (!(fesapiClass.Name.Contains("Abstract")) && generateXmlTag == "true") // impotant note: we assume that a class is // abstract if it contains "Abstract" in its // name { // we add an XML_TAG attribute EA.Attribute xmlTagAttribute = energisticsClass.Attributes.AddNew("XML_TAG", "char*"); xmlTagAttribute.IsStatic = true; xmlTagAttribute.IsConst = true; if (!(xmlTagAttribute.Update())) { Tool.showMessageBox(repository, xmlTagAttribute.GetLastError()); } energisticsClass.Attributes.Refresh(); // thanks to a tag, we tells that the XML_TAG attribute should be generated during the code generation. // Keep in mind that Energistics class attributes are not generated in fesapi by default since most of them // relies on gSOAP proxies attributes EA.AttributeTag generationTag = xmlTagAttribute.TaggedValues.AddNew(Constants.fesapiGenerationTagName, "true"); if (!(generationTag.Update())) { Tool.showMessageBox(repository, generationTag.GetLastError()); } // thanks to a tag, we tells that no getter should be automatically generated during the transformation // of the Energistics model into a C++ model EA.AttributeTag getterGenerationTag = xmlTagAttribute.TaggedValues.AddNew(Constants.fesapiGetterGenerationTagName, "false"); if (!(getterGenerationTag.Update())) { Tool.showMessageBox(repository, getterGenerationTag.GetLastError()); } // add the XML_TAG attributr getter EA.Method getXmlTagMethod = energisticsClass.Methods.AddNew("getXmlTag", "std::string"); getXmlTagMethod.Stereotype = "const"; getXmlTagMethod.Code = "return XML_TAG;"; getXmlTagMethod.Abstract = true; if (!(getXmlTagMethod.Update())) { Tool.showMessageBox(repository, getXmlTagMethod.GetLastError()); } energisticsClass.Methods.Refresh(); // tag the getter in order for its body to be generated into the class declaration EA.MethodTag getXmlTagMethodBodyLocationTag = getXmlTagMethod.TaggedValues.AddNew("bodyLocation", "classDec"); if (!(getXmlTagMethodBodyLocationTag.Update())) { Tool.showMessageBox(repository, getXmlTagMethodBodyLocationTag.GetLastError()); } getXmlTagMethod.TaggedValues.Refresh(); } }