Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


Presentation on theme: "An Examination of DSLs for Concisely Representing Model Traversals and Transformations Jeff Gray University of Alabama at Birmingham Gábor Karsai Vanderbilt."— 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 for Embedded 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 MM LRU FR FDE LRUVAR OBS UNIT MSG ALR

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

6 Tool Integration Framework (TIF) IMS models can be viewed in a web browser New tools can access the IMS directly through the CMI Legacy tools require a bi-directional tool adapter 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 CORBA

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

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 desired paths for traversals? Visitors: Actions to be taken  What to do? Phases of processing  Multiple passes over the structure

9 Entity_2 Top_Model Entity_1Component 1 * 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 & _res) { int count = 0; MetaEntity* type = MetaData::LookupEntity("RELEX","RELEX_Object"); vector ::iterator itr; vector * 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 Structured Specification of Translators (Traversal/Visitor) 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[...] } >; }

12 Generation of Traversal/Visitors … 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] }; … void Traversal_T::traverse(GME_4_0::Component_M& self, IMS::Component_M& parent) { vector _lst; self.get_failureModes(_lst); vector ::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 _lst; self.get_discrepancies(_lst); vector ::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 _lst; self.get_monitors(_lst); vector ::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 _lst; self.get_faultReports(_lst); vector ::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 _lst; self.get_subComponents(_lst); vector ::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 _lst; self.get_fmMonitor(_lst); vector ::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 _lst; self.get_fmDiscrepancy(_lst); vector ::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); } } …

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-Oriented Domain Modeling Please see October 2001 issue of Communications 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 Available for download at http://www.isis.vanderbilt.edu Please see November 2001 issue of IEEE Computer

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

17 Process of Using a Model Weaver GME Domain-Specific Weaver bit1 bit1 Structural ProcessingCompound GatesPerBit 37,153 NomBits 205,76 MaxBits 128,76 Enhanced FOO.XML bit1 bit1 Structural ProcessingCompound GatesPerBit 37,153 NomBits 205,76 MaxBits 128,76 FOO.XML 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); } Specification Aspects

18 Comp1 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(); } Quantification Over Base Code (AOP) Weavers ‘instrument’ code with advice pointcut pubIntf(Object o): call(public * com.borland.*.*(..)) && target(o); after(Object o) throwing (Error e): pubIntf(o) { log.write(o, e); … } after(Object o) throwing (Error e): pubIntf(o) { log.write(o, e); … } Comp2 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); } Comp1 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(); } Comp2 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); }

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 … select(p | p.name() == “Model*” && p.kind() == “StateFlow”)->Strategy3(); … Strategy1 Strategy2 Strategy3 StrategyN

20 The Metaweaver Framework Strategy Code Generator Strategies (C++) Strategy Specifications Specification Aspects 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); } XML ( Model Hierarchy )

21 Embedded Constraint Language Arithmetic Operators +, -, *, /, =,, =, <> Logical Operators and, or, xor, not, implies, if/then/else Collection Operator -> Property Operator. Standard OCL Collection Operators collection->size() : integer collection->forAll( x | f(x) ) : Boolean collection->select( x | f(x) ) : collection collection->exists( x | f(x) ) : Boolean 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 mods=XMLParser::models(components,""); nodeTypeVector selectVec1 = XMLParser::ConvertDomList(mods); nodeTypeVector selectVecTrue1 = new std::vector ; vector ::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 ::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


Download ppt "An Examination of DSLs for Concisely Representing Model Traversals and Transformations Jeff Gray University of Alabama at Birmingham Gábor Karsai Vanderbilt."

Similar presentations


Ads by Google