An Examination of DSLs for Concisely Representing Model Traversals and Transformations

34
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.

description

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. - PowerPoint PPT Presentation

Transcript of An Examination of DSLs for Concisely Representing Model Traversals and Transformations

Page 1: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

An Examination of DSLs for Concisely Representing

Model Traversals and TransformationsJeff 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.

Page 2: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

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

Page 3: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

Tool Integration

Page 4: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

Tool Integration

MMLRU

FR

FDE

LRU VAR

OBS

UNITMSG

ALR

Page 5: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

Integrated Model Server (IMS)

AEFRFMECA

ADVISE

GME

RELEX

BrowserCOM

CORBA

ADO

ADO

Text

Excel (csv)

IMS

Page 6: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

Tool Integration Framework (TIF)

ORB

Integrated Model

Browser

Legacy Tool 1

Tool Adapter

Integrated Tool

Naming Service

Legacy Tool N

Tool Adapter

Common Model Interface

Meta-Model Objects

IMS

Semantic Translation

Integrated Model Database

IMS models can be viewed in a web browser

New tools can access the IMS directly through the CMI

Legacy tools require abi-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

Page 7: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

Tool Integration Framework (TIF)

ORB

Integrated Model

Browser

Legacy Tool 1

Tool Adapter

Integrated Tool

Naming Service

Legacy Tool N

Tool Adapter

Common Model Interface

Meta-Model Objects

IMS

Semantic Translation

Integrated Model Database

IMS models can be viewed in a web browser

New tools can access the IMS directly through the CMI

Legacy tools require abi-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

Page 8: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

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

Page 9: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

Entity_2

Top_Model

Entity_1 Component

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 *;}

Page 10: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

Generation of Data Structuresparadigm 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;}

Page 11: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

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[...] } <<...>>;

}

Page 12: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

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<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); }}…

Page 13: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

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

Page 14: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

Aspect-OrientedDomain Modeling

Please see October 2001 issue of Communications of the ACM

Page 15: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

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

Page 16: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

Difficulties in Managing Constraints

A

B

c d e1 2

3

B

c d e1'' 2'' 4

F

B

c d e1' 2'

3'

4Multiple Levelsof Hierarchy Replicated

Structures

ContextSensitive

ChangeMaintenance???

Page 17: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

Process of Using a Model Weaver

GME

Domain-Specific

Weaver

<?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

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

Page 18: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

Comp1package 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 [[email protected]] * @author James Todd [[email protected]] */

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); … }

Comp2package 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 [[email protected]] * @author Jason Hunter [[email protected]] * @author James Todd [[email protected]] */

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); } }}

Comp1package 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 [[email protected]] * @author James Todd [[email protected]] */

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(); } }}

Comp2package 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 [[email protected]] * @author Jason Hunter [[email protected]] * @author James Todd [[email protected]] */

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); } }}

Page 19: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

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

Page 20: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

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)

Page 21: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

Embedded Constraint Language

Arithmetic Operators +, -, *, /, =, <, >, <=, >=, <>

Logical Operatorsand, or, xor, not, implies, if/then/else

Collection Operator ->

Property Operator .

Standard OCL Collection Operators

collection->size() : integercollection->forAll( x | f(x) ) : Booleancollection->select( x | f(x) ) : collectioncollection->exists( x | f(x) ) : Boolean

Included OCL Operators

Page 22: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

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

Page 23: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

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(…);

Page 24: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

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

Page 25: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

Analysis of Generated Code

Page 26: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

MSF to Generated Code

Lines of Code Bytes of Code Advise

MSF: 33 C++: 506

Ratio: 1::15.33

MSF: 761b C++: 14.79k

Ratio: 1::19.44 Relex

MSF: 34 C++: 538

Ratio: 1::15.82

MSF: 819b C++: 17.54k

Ratio: 1::21.42 FMECA

MSF: 44 C++: 802

Ratio: 1::18.22

MSF: 1.26k C++: 27.32k

Ratio: 1::21.68 AEFR

MSF: 49 C++: 639

Ratio: 1::13.04

MSF: 870b C++: 21.42k

Ratio: 1::24.62 GME

MSF: 58 C++: 922

Ratio: 1::15.89

MSF: 1.19k C++: 28.71k

Ratio: 1::24.13

Page 27: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

TVL to Generated Code

Lines of Code Bytes of Code Advise2IMS

TVL: 155 C++: 355

Ratio: 1::2.29

TVL: 4.03k C++: 8.78k

Ratio: 1::2.18 Relex2IMS

TVL: 351 C++: 523

Ratio: 1::1.49

TVL: 10.15k C++: 17.54k Ratio: 1::1.73

FMECA2IMS

TVL: 248 C++: 435

Ratio: 1::1.75

TVL: 7.85k C++: 12.10k Ratio: 1::1.54

AEFR2IMS

TVL: 192 C++: 497

Ratio: 1::2.59

TVL: 6.49k C++: 13.39k Ratio: 1::2.06

GME2IMS

TVL: 251 C++: 523

Ratio: 1::2.08

TVL: 7.22k C++: 14.27k Ratio: 1::1.98

Page 28: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

ECL to Generated Code Lines of

Code Bytes of Code

Power Distribution

ECL: 43 C++: 140

Ratio: 1::3.25

ECL: 859b C++: 3.08k

Ratio: 1::3.50

Processor Assignment

ECL: 39 C++: 137

Ratio: 1::3.50

ECL: 954b C++: 3.28k

Ratio: 1::3.44

Eager/Lazy

ECL: 85 C++: 230

Ratio: 1::2.71

ECL: 2.03k C++: 6.24k

Ratio: 1::3.07

Exhaustive State

Transition

ECL: 70 C++: 184

Ratio: 1::2.62

ECL: 1.92k C++: 5.14k

Ratio: 1::2.68

State Generation

ECL: 128 C++: 242

Ratio: 1::1.89

ECL: 3.42k C++: 6.76k

Ratio: 1::1.98

Page 29: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

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.

Page 30: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

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.

Page 31: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

Additional Slides

Page 32: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

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?

Page 33: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

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

Page 34: An Examination of DSLs for Concisely Representing  Model Traversals and Transformations

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