1 / 34

An Examination of DSLs for Concisely Representing Model Traversals and Transformations

An Examination of DSLs for Concisely Representing Model Traversals and Transformations. Jeff Gray University of Alabama at Birmingham Gábor Karsai Vanderbilt University/ISIS HICSS-36.

hollye
Download Presentation

An Examination of DSLs for Concisely Representing Model Traversals and Transformations

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. An Examination of DSLs for Concisely Representing Model Traversals and Transformations Jeff Gray University of Alabama at Birmingham Gábor Karsai Vanderbilt University/ISIS HICSS-36 This work is supported by the DARPA IXO, under the Program Composition forEmbedded Systems (PCES) program, Contract Number: F33615-00-C-1695 Support for this project was also provided by Boeing.

  2. Overview • Three DSLs in two different applications • Applications: Tool integration and aspect-oriented domain modeling (AODM) • Focus of DSLs: • Generation of complex data structures from high-level specifications • Synthesis of iterative processes • Generation of API wrappers from high-level specs • Quantitative description of generated code

  3. Tool Integration

  4. Tool Integration Tool-X Tool-Y LRU MM LRU VAR FR FDE MSG UNIT OBS ALR Integrated Model

  5. Integrated Model Server (IMS) AEFR FMECA ADO Excel (csv) Text ADO IMS RELEX ADVISE CORBA COM Browser GME

  6. Tool Integration Framework (TIF) Legacy tools require a bi-directional tool adapter IMS models can be viewed in a web browser New tools can access the IMS directly through the CMI CORBA The CMI is specified in CORBA IDL and defines rules and data structures for accessing the IMS MS Repository sits on top of an ODBC database; currently Access or SQL Server

  7. Tool Integration Framework (TIF) Legacy tools require a bi-directional tool adapter Focus of this portion of the talk: IMS models can be viewed in a web browser New tools can access the IMS directly through the CMI DSLs for representing model translation as traversal/visitor specifications DSLs for representing tool models as stored in the CMI CORBA The CMI is specified in CORBA IDL and defines rules and data structures for accessing the IMS

  8. Pieces of the Translation • Structure of the models: Objects to be traversed • What are the possible paths for traversals? • Traversal sequences: How to traverse? • What are the desiredpaths for traversals? • Visitors: Actions to be taken • What to do? • Phases of processing • Multiple passes over the structure

  9. Top_Model Entity_1 Component 1 * Entity_2 Tool Specification (Structure) paradigm Foo; model Top_Model { ... part Component components; } model Component { ... part Entity_1 ent_1; part Entity_2 ent_2; part Component subComponents; rel Rel aRel } entity Entity_1 { ... } entity Entity_2 { ... } relation Rel { Entity_1 src 1<->Entity_2 dst *; }

  10. Generation of Data Structures paradigm RELEX; model RELEX_Model { attr string Name; part RELEX_Object objects; part Failure_Mode failure_Modes; rel RELEX_Failure_Mode rel_FM; } entity RELEX_Object { attr string Name; attr string Part_Number; attr string User_Text; attr string Reference; attr double Failure_Rate; } entity Failure_Mode { attr string Failure_Mode; attr string Local_Effects; attr string Next_Effects; attr string End_Effects; attr string Failure_Detection_Method; attr long Mode_Severity_Code; attr double Failure_Mode_Ratio; attr double Failure_Effect_Probability; attr double Failure_Rate; } relation RELEX_Failure_Mode { RELEX_Object Owner 1 <-> Failure_Mode Failures *; } … int RELEX_Model_M::get_objects(vector<RELEX_Object_E>& _res) { int count = 0; MetaEntity* type = MetaData::LookupEntity("RELEX","RELEX_Object"); vector<InstEntity*>::iterator itr; vector<InstEntity*>* list = obj->parts(); for(itr = list->begin(); itr != list->end(); itr++) { if((*itr)->type() == type) { _res.push_back(RELEX_Object_E(*itr)); count++; } } return count; } …

  11. visitor Visitor { at Component[...] <<...>> traverse[...]; at Entity_1[...] <<...>>; at Entity_2[...] <<...>>; at Rel[...] traverse[...]; } traversal Traversal using Visitor { from Top_Model ->[…] <<...>> to { components[...] } <<...>>; from Component[...] to { entity_1[...], entity_2[...], subComponents[...], rel[...] }; from Rel[...] <<...>> to {src[...], dst[...] } <<...>>; } Structured Specification of Translators(Traversal/Visitor)

  12. Generation of Traversal/Visitors … void Traversal_T::traverse(GME_4_0::Component_M& self, IMS::Component_M& parent) { vector<GME_4_0::FailureMode_E> _lst; self.get_failureModes(_lst); vector<GME_4_0::FailureMode_E>::iterator _itr; for(_itr = _lst.begin(); _itr != _lst.end(); _itr++) { GME_4_0::FailureMode_E arg=GME_4_0::FailureMode_E(*_itr); vis->visit(arg,parent,fMap); } vector<GME_4_0::Discrepancy_E> _lst; self.get_discrepancies(_lst); vector<GME_4_0::Discrepancy_E>::iterator _itr; for(_itr = _lst.begin(); _itr != _lst.end(); _itr++) { GME_4_0::Discrepancy_E arg=GME_4_0::Discrepancy_E(*_itr); vis->visit(arg,parent,dMap); } vector<GME_4_0::Monitor_E> _lst; self.get_monitors(_lst); vector<GME_4_0::Monitor_E>::iterator _itr; for(_itr = _lst.begin(); _itr != _lst.end(); _itr++) { GME_4_0::Monitor_E arg = GME_4_0::Monitor_E(*_itr); vis->visit(arg,parent,mMap); } vector<GME_4_0::Fault_Report_E> _lst; self.get_faultReports(_lst); vector<GME_4_0::Fault_Report_E>::iterator _itr; for(_itr = _lst.begin(); _itr != _lst.end(); _itr++) { GME_4_0::Fault_Report_E arg=GME_4_0::Fault_Report_E(*_itr); vis->visit(arg,parent); } vector<GME_4_0::Component_M> _lst; self.get_subComponents(_lst); vector<GME_4_0::Component_M>::iterator _itr; for(_itr = _lst.begin(); _itr != _lst.end(); _itr++) { GME_4_0::Component_M arg = GME_4_0::Component_M(*_itr); vis->visit(arg,parent,pcMap); } vector<GME_4_0::FMMonitor_R> _lst; self.get_fmMonitor(_lst); vector<GME_4_0::FMMonitor_R>::iterator _itr; for(_itr = _lst.begin(); _itr != _lst.end(); _itr++) { GME_4_0::FMMonitor_R arg = GME_4_0::FMMonitor_R(*_itr); vis->visit(arg,parent,fMap,mMap); } vector<GME_4_0::FMDiscrepancy_R> _lst; self.get_fmDiscrepancy(_lst); vector<GME_4_0::FMDiscrepancy_R>::iterator _itr; for(_itr = _lst.begin(); _itr != _lst.end(); _itr++) { GME_4_0::FMDiscrepancy_R arg=GME_4_0::FMDiscrepancy_R(*_itr); vis->visit(arg,parent,fMap,dMap); } } … … from Component[IMS::Component_M& parent] to { failureModes[parent,fMap], discrepancies[parent,dMap], monitors[parent,mMap], faultReports[parent], subComponents[parent,pcMap], fmMonitor[parent,fMap,mMap], fmDiscrepancy[parent,fMap,dMap] }; …

  13. Achieved Goals - Tool Integration • Using a DSL, the underlying CORBA data structures and service calls that are needed to perform the model integration are hidden. • Using a DSL, the often tedious and repetitive code fragments that are needed for iteration and transformation can be more concisely/intuitively specified. • Separation of concerns: • Cleaner solution by separating semantic (translator) and syntactic (adapter) issues

  14. Aspect-OrientedDomain Modeling Please see October 2001 issue ofCommunications of the ACM

  15. Model-Integrated Computing (MIC) with the Generic Modeling Environment (GME) • Generic Modeling Environment (GME) is a domain-specific modeling tool • Grew out of over 14 years of research on computer-based systems in aerospace, instrumentation, manufacturing and robotics. • It can be utilized in many different domains by providing a meta-level paradigm description. Paradigm describes all of the entities of the domain, as well as valid relationships • A modeler first loads the domain paradigm and then constructs new models in that domain Please see November 2001 issue of IEEE Computer Available for download at http://www.isis.vanderbilt.edu

  16. Difficulties in Managing Constraints Change Maintenance??? Multiple Levels of Hierarchy 4 A Replicated Structures 3 B F 1 2 c d e 3' B B 4 1' 2' 1'' 2'' c d e c d e Context Sensitive

  17. GME <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE project SYSTEM "mga.dtd"> <project guid="{00000000-0000-0000-0000-000000000000}" cdate="Thu Nov 30 14:15:40 2000" mdate="Thu Nov 30 14:15:40 2000" metaguid="{00000000-0000-0000-0000-000000000000}" metaname="PCES"> <name>bit1</name> <comment></comment> <author></author> <folder id="id-006a-00000001" kind="RootFolder"> <name>bit1</name> <folder id="id-006a-00000002" kind="Structural"> <name>Structural</name> <model id="id-0065-00000001" kind="ProcessingCompound"> <name>ProcessingCompound</name> <attribute kind="Description" status="meta"> <value></value> </attribute> <atom id="id-0066-00000007" kind="Attribute" role="Attrib"> <name>GatesPerBit</name> <regnode name="PartRegs"> <value></value> <regnode name="StructuralAspect"> <value></value> <regnode name="Position" isopaque="yes"> <value>37,153</value> </regnode> </regnode> </regnode> <attribute kind="Value" status="meta"> <value></value> </attribute> </atom> <atom id="id-0066-00000006" kind="Attribute" role="Attrib"> <name>NomBits</name> <regnode name="PartRegs"> <value></value> <regnode name="StructuralAspect"> <value></value> <regnode name="Position" isopaque="yes"> <value>205,76</value> </regnode> </regnode> </regnode> <attribute kind="Value" status="meta"> <value></value> </attribute> </atom> <atom id="id-0066-00000005" kind="Attribute" role="Attrib"> <name>MaxBits</name> <regnode name="PartRegs"> <value></value> <regnode name="StructuralAspect"> <value></value> <regnode name="Position" isopaque="yes"> <value>128,76</value> </regnode> </regnode> </regnode> Enhanced FOO.XML <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE project SYSTEM "mga.dtd"> <project guid="{00000000-0000-0000-0000-000000000000}" cdate="Thu Nov 30 14:15:40 2000" mdate="Thu Nov 30 14:15:40 2000" metaguid="{00000000-0000-0000-0000-000000000000}" metaname="PCES"> <name>bit1</name> <comment></comment> <author></author> <folder id="id-006a-00000001" kind="RootFolder"> <name>bit1</name> <folder id="id-006a-00000002" kind="Structural"> <name>Structural</name> <model id="id-0065-00000001" kind="ProcessingCompound"> <name>ProcessingCompound</name> <attribute kind="Description" status="meta"> <value></value> </attribute> <atom id="id-0066-00000007" kind="Attribute" role="Attrib"> <name>GatesPerBit</name> <regnode name="PartRegs"> <value></value> <regnode name="StructuralAspect"> <value></value> <regnode name="Position" isopaque="yes"> <value>37,153</value> </regnode> </regnode> </regnode> <attribute kind="Value" status="meta"> <value></value> </attribute> </atom> <atom id="id-0066-00000006" kind="Attribute" role="Attrib"> <name>NomBits</name> <regnode name="PartRegs"> <value></value> <regnode name="StructuralAspect"> <value></value> <regnode name="Position" isopaque="yes"> <value>205,76</value> </regnode> </regnode> </regnode> <attribute kind="Value" status="meta"> <value></value> </attribute> </atom> <atom id="id-0066-00000005" kind="Attribute" role="Attrib"> <name>MaxBits</name> <regnode name="PartRegs"> <value></value> <regnode name="StructuralAspect"> <value></value> <regnode name="Position" isopaque="yes"> <value>128,76</value> </regnode> </regnode> </regnode> FOO.XML Domain-Specific Weaver Specification Aspects constraint FOOB2 { // apply a specific constraint to “B2” only in Structural models("ProcessingCompound")-> select(p | p.name() == "B2")->PowerStrategy(1, 100); } constraint FOOBStar { // apply a specific constraint to all nodes beginning with “B” - use wildcard in Structural models("ProcessingCompound")-> select(p | p.name() == "B*")->PowerStrategy(1, 100); } Process of Using a Model Weaver

  18. Comp2 Comp2 Comp1 Comp1 package org.apache.tomcat.session; import org.apache.tomcat.util.*; import org.apache.tomcat.core.*; import java.io.*; import java.net.*; import java.util.*; import javax.servlet.http.*; /** * * @author James Duncan Davidson [duncan@eng.sun.com] * @author Jason Hunter [jch@eng.sun.com] * @author James Todd [gonzo@eng.sun.com] */ public class ServerSessionManager implements SessionManager { private StringManager sm = StringManager.getManager("org.apache.tomcat.session"); private static ServerSessionManager manager; // = new ServerSessionManager(); protected int inactiveInterval = -1; static { manager = new ServerSessionManager(); } public static ServerSessionManager getManager() { return manager; } private Hashtable sessions = new Hashtable(); private Reaper reaper; private ServerSessionManager() { reaper = Reaper.getReaper(); reaper.setServerSessionManager(this); reaper.start(); } public void accessed( Context ctx, Request req, String id ) { ApplicationSession apS=(ApplicationSession)findSession( ctx, id); if( apS==null) return; ServerSession servS=apS.getServerSession(); servS.accessed(); apS.accessed(); // cache it - no need to compute it again req.setSession( apS ); } public HttpSession createSession(Context ctx) { String sessionId = SessionIdGenerator.generateId(); ServerSession session = new ServerSession(sessionId); sessions.put(sessionId, session); if(-1 != inactiveInterval) { session.setMaxInactiveInterval(inactiveInterval); } return session.getApplicationSession( ctx, true ); } public HttpSession findSession(Context ctx, String id) { ServerSession sSession=(ServerSession)sessions.get(id); if(sSession==null) return null; return sSession.getApplicationSession(ctx, false); } package org.apache.tomcat.session; import org.apache.tomcat.util.*; import org.apache.tomcat.core.*; import java.io.*; import java.net.*; import java.util.*; import javax.servlet.http.*; /** * * @author James Duncan Davidson [duncan@eng.sun.com] * @author Jason Hunter [jch@eng.sun.com] * @author James Todd [gonzo@eng.sun.com] */ public class ServerSessionManager implements SessionManager { private StringManager sm = StringManager.getManager("org.apache.tomcat.session"); private static ServerSessionManager manager; // = new ServerSessionManager(); protected int inactiveInterval = -1; static { manager = new ServerSessionManager(); } public static ServerSessionManager getManager() { return manager; } private Hashtable sessions = new Hashtable(); private Reaper reaper; private ServerSessionManager() { reaper = Reaper.getReaper(); reaper.setServerSessionManager(this); reaper.start(); } public void accessed( Context ctx, Request req, String id ) { ApplicationSession apS=(ApplicationSession)findSession( ctx, id); if( apS==null) return; ServerSession servS=apS.getServerSession(); servS.accessed(); apS.accessed(); // cache it - no need to compute it again req.setSession( apS ); } public HttpSession createSession(Context ctx) { String sessionId = SessionIdGenerator.generateId(); ServerSession session = new ServerSession(sessionId); sessions.put(sessionId, session); if(-1 != inactiveInterval) { session.setMaxInactiveInterval(inactiveInterval); } return session.getApplicationSession( ctx, true ); } public HttpSession findSession(Context ctx, String id) { ServerSession sSession=(ServerSession)sessions.get(id); if(sSession==null) return null; return sSession.getApplicationSession(ctx, false); } // XXX // sync'd for safty -- no other thread should be getting something // from this while we are reaping. This isn't the most optimal // solution for this, but we'll determine something else later. synchronized void reap() { Enumeration enum = sessions.keys(); while (enum.hasMoreElements()) { Object key = enum.nextElement(); ServerSession session = (ServerSession)sessions.get(key); session.reap(); session.validate(); } } synchronized void removeSession(ServerSession session) { String id = session.getId(); session.invalidate(); sessions.remove(id); } public void removeSessions(Context context) { Enumeration enum = sessions.keys(); while (enum.hasMoreElements()) { Object key = enum.nextElement(); ServerSession session = (ServerSession)sessions.get(key); ApplicationSession appSession = session.getApplicationSession(context, false); if (appSession != null) { appSession.invalidate(); } } } /** * Used by context to configure the session manager's inactivity timeout. * * The SessionManager may have some default session time out, the * Context on the other hand has it's timeout set by the deployment * descriptor (web.xml). This method lets the Context conforgure the * session manager according to this value. * * @param minutes The session inactivity timeout in minutes. */ public void setSessionTimeOut(int minutes) { if(-1 != minutes) { // The manager works with seconds... inactiveInterval = (minutes * 60); } } } // XXX // sync'd for safty -- no other thread should be getting something // from this while we are reaping. This isn't the most optimal // solution for this, but we'll determine something else later. synchronized void reap() { Enumeration enum = sessions.keys(); while (enum.hasMoreElements()) { Object key = enum.nextElement(); ServerSession session = (ServerSession)sessions.get(key); session.reap(); session.validate(); } } synchronized void removeSession(ServerSession session) { String id = session.getId(); session.invalidate(); sessions.remove(id); } public void removeSessions(Context context) { Enumeration enum = sessions.keys(); while (enum.hasMoreElements()) { Object key = enum.nextElement(); ServerSession session = (ServerSession)sessions.get(key); ApplicationSession appSession = session.getApplicationSession(context, false); if (appSession != null) { appSession.invalidate(); } } } /** * Used by context to configure the session manager's inactivity timeout. * * The SessionManager may have some default session time out, the * Context on the other hand has it's timeout set by the deployment * descriptor (web.xml). This method lets the Context conforgure the * session manager according to this value. * * @param minutes The session inactivity timeout in minutes. */ public void setSessionTimeOut(int minutes) { if(-1 != minutes) { // The manager works with seconds... inactiveInterval = (minutes * 60); } } } package org.apache.tomcat.session; import org.apache.tomcat.core.*; import org.apache.tomcat.util.StringManager; import java.io.*; import java.net.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; /** * Core implementation of a server session * * @author James Duncan Davidson [duncan@eng.sun.com] * @author James Todd [gonzo@eng.sun.com] */ public class ServerSession { private StringManager sm = StringManager.getManager("org.apache.tomcat.session"); private Hashtable values = new Hashtable(); private Hashtable appSessions = new Hashtable(); private String id; private long creationTime = System.currentTimeMillis();; private long thisAccessTime = creationTime; private long lastAccessed = creationTime; private int inactiveInterval = -1; ServerSession(String id) { this.id = id; } public String getId() { return id; } public long getCreationTime() { return creationTime; } public long getLastAccessedTime() { return lastAccessed; } public ApplicationSession getApplicationSession(Context context, boolean create) { ApplicationSession appSession = (ApplicationSession)appSessions.get(context); if (appSession == null && create) { // XXX // sync to ensure valid? appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); } // XXX // make sure that we haven't gone over the end of our // inactive interval -- if so, invalidate and create // a new appSession return appSession; } void removeApplicationSession(Context context) { appSessions.remove(context); } /** * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. */ void accessed() { // set last accessed to thisAccessTime as it will be left over // from the previous access lastAccessed = thisAccessTime; thisAccessTime = System.currentTimeMillis(); } void validate() package org.apache.tomcat.session; import org.apache.tomcat.core.*; import org.apache.tomcat.util.StringManager; import java.io.*; import java.net.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; /** * Core implementation of a server session * * @author James Duncan Davidson [duncan@eng.sun.com] * @author James Todd [gonzo@eng.sun.com] */ public class ServerSession { private StringManager sm = StringManager.getManager("org.apache.tomcat.session"); private Hashtable values = new Hashtable(); private Hashtable appSessions = new Hashtable(); private String id; private long creationTime = System.currentTimeMillis();; private long thisAccessTime = creationTime; private long lastAccessed = creationTime; private int inactiveInterval = -1; ServerSession(String id) { this.id = id; } public String getId() { return id; } public long getCreationTime() { return creationTime; } public long getLastAccessedTime() { return lastAccessed; } public ApplicationSession getApplicationSession(Context context, boolean create) { ApplicationSession appSession = (ApplicationSession)appSessions.get(context); if (appSession == null && create) { // XXX // sync to ensure valid? appSession = new ApplicationSession(id, this, context); appSessions.put(context, appSession); } // XXX // make sure that we haven't gone over the end of our // inactive interval -- if so, invalidate and create // a new appSession return appSession; } void removeApplicationSession(Context context) { appSessions.remove(context); } /** * Called by context when request comes in so that accesses and * inactivities can be dealt with accordingly. */ void accessed() { // set last accessed to thisAccessTime as it will be left over // from the previous access lastAccessed = thisAccessTime; thisAccessTime = System.currentTimeMillis(); } void validate() void validate() { // if we have an inactive interval, check to see if // we've exceeded it if (inactiveInterval != -1) { int thisInterval = (int)(System.currentTimeMillis() - lastAccessed) / 1000; if (thisInterval > inactiveInterval) { invalidate(); ServerSessionManager ssm = ServerSessionManager.getManager(); ssm.removeSession(this); } } } synchronized void invalidate() { Enumeration enum = appSessions.keys(); while (enum.hasMoreElements()) { Object key = enum.nextElement(); ApplicationSession appSession = (ApplicationSession)appSessions.get(key); appSession.invalidate(); } } public void putValue(String name, Object value) { if (name == null) { String msg = sm.getString("serverSession.value.iae"); throw new IllegalArgumentException(msg); } removeValue(name); // remove any existing binding values.put(name, value); } public Object getValue(String name) { if (name == null) { String msg = sm.getString("serverSession.value.iae"); throw new IllegalArgumentException(msg); } return values.get(name); } public Enumeration getValueNames() { return values.keys(); } public void removeValue(String name) { values.remove(name); } public void setMaxInactiveInterval(int interval) { inactiveInterval = interval; } public int getMaxInactiveInterval() { return inactiveInterval; } // XXX // sync'd for safty -- no other thread should be getting something // from this while we are reaping. This isn't the most optimal // solution for this, but we'll determine something else later. synchronized void reap() { Enumeration enum = appSessions.keys(); while (enum.hasMoreElements()) { Object key = enum.nextElement(); ApplicationSession appSession = (ApplicationSession)appSessions.get(key); appSession.validate(); } } } void validate() { // if we have an inactive interval, check to see if // we've exceeded it if (inactiveInterval != -1) { int thisInterval = (int)(System.currentTimeMillis() - lastAccessed) / 1000; if (thisInterval > inactiveInterval) { invalidate(); ServerSessionManager ssm = ServerSessionManager.getManager(); ssm.removeSession(this); } } } synchronized void invalidate() { Enumeration enum = appSessions.keys(); while (enum.hasMoreElements()) { Object key = enum.nextElement(); ApplicationSession appSession = (ApplicationSession)appSessions.get(key); appSession.invalidate(); } } public void putValue(String name, Object value) { if (name == null) { String msg = sm.getString("serverSession.value.iae"); throw new IllegalArgumentException(msg); } removeValue(name); // remove any existing binding values.put(name, value); } public Object getValue(String name) { if (name == null) { String msg = sm.getString("serverSession.value.iae"); throw new IllegalArgumentException(msg); } return values.get(name); } public Enumeration getValueNames() { return values.keys(); } public void removeValue(String name) { values.remove(name); } public void setMaxInactiveInterval(int interval) { inactiveInterval = interval; } public int getMaxInactiveInterval() { return inactiveInterval; } // XXX // sync'd for safty -- no other thread should be getting something // from this while we are reaping. This isn't the most optimal // solution for this, but we'll determine something else later. synchronized void reap() { Enumeration enum = appSessions.keys(); while (enum.hasMoreElements()) { Object key = enum.nextElement(); ApplicationSession appSession = (ApplicationSession)appSessions.get(key); appSession.validate(); } } } Quantification Over Base Code (AOP) • Weavers ‘instrument’ code with advice after(Object o) throwing (Error e): pubIntf(o) { log.write(o, e); … } pointcut pubIntf(Object o): call(public * com.borland.*.*(..)) && target(o);

  19. Quantification Over a Domain Model (AODM) • Apply AO Weaving concepts to Model-based systems • Weavers ‘Decorate’ Models with attributes & constraints • Weavers compose new model constructs Strategy1 Strategy2 Strategy3 StrategyN … select(p | p.name() == “Model*” && p.kind() == “StateFlow”)->Strategy3(); …

  20. The Metaweaver Framework Specification Aspects XML Parser Strategies (C++) Aspect Parser XML (Model Hierarchy) Strategy Specifications Strategy Code Generator strategy ApplyConstraint(constraintName : string, expression : string) { addAtom("OCLConstraint", "Constraint", constraintName).addAttribute("Expression", expression); } strategy RemoveConstraint(constraintName : string) { findAtom(constraintName).removeChild(); } strategy ReplaceConstraint(constraintName : string, expression : string) { RemoveConstraint(constraintName); ApplyConstraint(constraintName, expression); }

  21. Embedded Constraint Language Included OCL Operators

  22. Embedded Constraint Language (ECL) • Traditional OCL has been strictly a declarative query language • New uses require an imperative procedural style • Addition of side effects into model • Examples: • addAtom(…),findAtom(…) • addAttribute(…),findAttribute(…) • removeNode(…) • Support for recursion • Chaining of strategies (procedure calls) • Inlined C++ code

  23. Generation of ECL … components.models("")->select(c |c.id() == refID)->DetermineLaziness(); … CComPtr<IXMLDOMNodeList> mods=XMLParser::models(components,""); nodeTypeVector selectVec1 = XMLParser::ConvertDomList(mods); nodeTypeVector selectVecTrue1 = new std::vector<nodeType>; vector<nodeType>::iterator itrSelect1; for(itrSelect1 = selectVec1->begin(); itrSelect1 != selectVec1->end(); itrSelect1++) { nodeType selectNode1 = (*itrSelect1); nodeType c; c = selectNode1; CComBSTR id0 = XMLParser::id(c); ClData varforward1(id0); ClData varforward2(refID); bool varforward3 = varforward1 == varforward2; if(varforward3) selectVecTrue1->push_back(*itrSelect1); } vector<nodeType>::iterator itrCollCall1; for(itrCollCall1 = selectVecTrue1->begin(); itrCollCall1 != selectVecTrue1->end(); itrCollCall1++) DetermineLaziness::apply(…);

  24. Achieved Goals - AODM • Using a DSL, the modeler is shielded from the details of the core XML Document Object Model (DOM) API calls. • Using a DSL, the specification of the navigation within the domain models (while performing transformations) is raised to a higher level of abstraction

  25. Analysis of Generated Code

  26. MSF to Generated Code

  27. TVL to Generated Code

  28. ECL to Generated Code

  29. Concluding Remarks-Benefits of DSL use in these Two Projects • The tedious and mundane parts of writing a program are automated in the translation from the DSL to a traditional programming language. • Repetitive code sequences are generated automatically instead of the error-prone manual cut-and-paste method. The generation of such tedious code also has advantages in the maintenance phase of a project’s lifecycle. • Solutions can be constructed quickly because the programmer can more easily focus on the key abstractions. A DSL hides the underlying details of the solution space as implemented in a traditional programming language.

  30. Concluding Quotes • Niklaus Wirth: We must recognize the strong and undeniable influence that our language exerts on our ways of thinking and, in fact, delimits the abstract space in which we can formulate – give form to – our thoughts. • George Polya: An important step in solving a problem is to choose the notation. It should be done carefully. The time we spend now on choosing the notation may be well repaid by the time we save later avoiding hesitation and confusion. Moreover, choosing the notation carefully, we have to think sharply of the elements of the problem which must be denoted. Thus, choosing a suitable notation may contribute essentially to understanding the problem. • Ted Biggerstaff: The first order term in the success equation of reuse is the amount of domain-specific content and the second order term is the specific technology chosen in which to represent that content.

  31. Additional Slides

  32. Evaluating Tool Integration Solutions • How much time and effort does it cost to integrate a new tool? • How scalable is the integration approach? • How much expert knowledge is needed to realize an integration solution? • What is the coupling between the individual tools and the integration technology?

  33. Development Effort • Translators can be written within a few man-days • Average translator was 225 lines of traversal/visitor code • Tool Adapter development depends on: • Complexity of tool • Complexity of the tool’s data access mechanism (e.g., ADO, COM, comma separated values) • Developer experience with previous Tool Adapters • Our average development time for a bi-directional Tool Adapter is about 10 person-weeks

  34. Lessons Learned • Successful integration of 5 tools • Separation of concerns: • Cleaner solution by separating semantic and syntactic issues • Framework approach using software generators • infrastructural elements • tool-specific translators (componentized) • traversal/visitor specification language

More Related