diff --git a/AndroidAppGenerator.java b/AndroidAppGenerator.java new file mode 100644 index 00000000..16203d79 --- /dev/null +++ b/AndroidAppGenerator.java @@ -0,0 +1,564 @@ +import java.util.Vector; +import java.io.*; + + +public class AndroidAppGenerator extends AppGenerator +{ + + public void modelFacade(Vector usecases, CGSpec cgs, Vector entities, Vector types, PrintWriter out) + { // String ename = e.getName(); + // Vector atts = e.getAttributes(); + + // String evc = ename + "ViewController"; + // String evo = ename + "ValueObject"; + // String resvo = ename.toLowerCase() + "_vo"; + // String populateResult = createVOStatement(e,atts); + + out.println("package com.example.app;"); + out.println(); + + out.println("import android.content.Context;"); + out.println("import java.util.ArrayList;"); + out.println("import java.util.HashMap;"); + out.println("import java.util.List;"); + out.println("import java.util.Map;"); + out.println(""); + out.println("public class ModelFacade"); + out.println("{ Dbi dbi; "); + out.println(); + out.println(" static ModelFacade instance = null; "); + out.println(); + out.println(" public static ModelFacade getInstance(Context context)"); + out.println(" { if (instance == null) "); + out.println(" { instance = new ModelFacade(context); }"); + out.println(" return instance;"); + out.println(" }"); + out.println(); + out.println(); + + for (int i = 0; i < entities.size(); i++) + { Entity ent = (Entity) entities.get(i); + if (ent.isDerived()) { } + else + { String ename = ent.getName(); + out.println(" " + ename + "VO current" + ename + " = null;"); + out.println(); + out.println(" public List<" + ename + "VO> current" + + ename + "s = new ArrayList<" + ename + "VO>();"); + out.println(); + } + } + + out.println(" private ModelFacade(Context context)"); + out.println(" { dbi = new Dbi(context); }"); + out.println(); + + // if e is persistent, include a Dbi + + // System.out.println("import Foundation"); + // System.out.println("import Glibc"); + // System.out.println(""); + // System.out.println("class ModelFacade"); + // System.out.println("{ "); + + /* String extractatts = ""; + for (int x = 0; x < atts.size(); x++) + { Attribute att = (Attribute) atts.get(x); + Type atype = att.getType(); + if (atype != null) + { extractatts = extractatts + " var " + att + " : " + atype.getSwift() + " = vo." + att + "\n"; + } + } */ + + // System.out.println(usecases); + + for (int y = 0; y < usecases.size(); y++) + { if (usecases.get(y) instanceof UseCase) + { UseCase uc = (UseCase) usecases.get(y); + Vector pars = uc.getParameters(); + Attribute res = uc.getResultParameter(); + String partext = ""; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + partext = partext + partype.getJava7() + " " + par.getName(); + if (i < pars.size()-1) + { partext = partext + ", "; } + } + + String restype = "void"; + if (res != null) + { restype = res.getType().getJava7(); } + + out.println(" public " + restype + " " + uc.getName() + "(" + partext + ")"); + + out.println(" { "); + if (res != null) + { out.println(" " + res.getType().getJava7() + " " + res.getName() + ";"); } + + // out.println(extractatts); + out.println(uc.cgActivity(cgs,entities,types)); + // out.println(uc.cg(cgs)); + // System.out.println(" func " + uc.getName() + "(_ vo : " + evo + ") : " + evo); + // System.out.println(" { "); + // System.out.println(extractatts); + + // out.println(uc.cgActivity(cgs,entities,types)); + // out.println(populateResult); + // out.println(" return " + resvo); + if (res != null) + { out.println(" return result;"); } + + out.println(" }"); + out.println(); + + // String act = uc.activity.cg(cgs); + // System.out.println(uc.cgActivity(cgs,entities,types)); + // System.out.println(populateResult); + // System.out.println(" return " + resvo); + // System.out.println(" }"); + } + } + + for (int j = 0; j < entities.size(); j++) + { Entity ee = (Entity) entities.get(j); + if (ee.isDerived()) { continue; } + + String item = ee.getName(); + out.println(" public List<" + item + "VO> list" + item + "()"); + out.println(" { current" + item + "s = dbi.list" + item + "();"); + out.println(" return current" + item + "s;"); + out.println(" }"); + out.println(); + + out.println(" public List stringList" + item + "()"); + out.println(" { current" + item + "s = dbi.list" + item + "();"); + out.println(" List res = new ArrayList();"); + out.println(" for (int x = 0; x < current" + item + "s.size(); x++)"); + out.println(" { " + item + "VO _item = (" + item + "VO) current" + item + "s.get(x);"); + out.println(" res.add(_item + \"\");"); + out.println(" }"); + out.println(" return res;"); + out.println(" }"); + out.println(); + + Attribute key = ee.getPrincipalPK(); + if (key != null) + { Vector atts = ee.getAttributes(); + out.println(" private " + item + " get" + item + "ByPK(String _val)"); + out.println(" { ArrayList<" + item + "VO> _res = dbi.searchBy" + item + key + "(_val);"); + out.println(" if (_res.size() == 0)"); + out.println(" { return null; }"); + out.println(" else"); + out.println(" { " + item + "VO _vo = _res.get(0);"); + out.println(" " + item + " _itemx = new " + item + "(_val);"); + for (int k = 0; k < atts.size(); k++) + { Attribute att = (Attribute) atts.get(k); + String aname = att.getName(); + out.println(" _itemx." + aname + " = _vo." + aname + ";"); + } + out.println(" return _itemx;"); + out.println(" }"); + out.println(" }"); + out.println(); + } + + out.println(" public void setSelected" + item + "(" + item + "VO x)"); + out.println(" { current" + item + " = x; }"); + out.println(); + + out.println(" public void setSelected" + item + "(int i)"); + out.println(" { if (i < current" + item + "s.size())"); + out.println(" { current" + item + " = current" + item + "s.get(i); }"); + out.println(" }"); + out.println(); + + out.println(" public " + item + "VO getSelected" + item + "()"); + out.println(" { return current" + item + "; }"); + out.println(); + + out.println(" public void edit" + item + "(" + item + "VO _x)"); + out.println(" { dbi.edit" + item + "(_x); "); + out.println(" current" + item + " = _x;"); + out.println(" }"); + out.println(); + + out.println(" public void create" + item + "(" + item + "VO _x)"); + out.println(" { dbi.create" + item + "(_x);"); + out.println(" current" + item + " = _x;"); + out.println(" }"); + out.println(); + + out.println(" public void delete" + item + "(String _id)"); + out.println(" { dbi.delete" + item + "(_id);"); + out.println(" current" + item + " = null;"); + out.println(" }"); + out.println(); + + Vector atts = ee.getAttributes(); + for (int i = 0; i < atts.size(); i++) + { Attribute att = (Attribute) atts.get(i); + String attnme = att.getName(); + Type atttyp = att.getType(); + String typ = atttyp.getJava7(); + + out.println(" public List<" + item + "VO> searchBy" + item + attnme + "(String " + attnme + "x)"); + out.println(" { current" + item + "s = dbi.searchBy" + item + attnme + "(" + attnme + "x);"); + out.println(" return current" + item + "s;"); + out.println(" }"); + out.println(); + } + } + out.println("}"); + // System.out.println("}") + + } + + public String createVOStatement(Entity e, Vector atts) + { String ename = e.getName(); + // String evc = ename + "ViewController"; + String vo = ename.toLowerCase() + "_vo"; + String evo = ename + "ValueObject"; + String attlist = ""; + for (int x = 0; x < atts.size(); x++) + { Attribute att = (Attribute) atts.get(x); + String aname = att.getName(); + attlist = attlist + aname; + if (x < atts.size()-1) + { attlist = attlist + ","; } + } + + String res = " var " + vo + " : " + evo + " = " + evo + "(" + attlist + ")"; + return res; + } + + public void singlePageApp(UseCase uc, CGSpec cgs, PrintWriter out) + { String ucname = uc.getName(); + String evc = ucname + "ViewController"; + // String evo = ename + "ValueObject"; + // String vo = evo.toLowerCase(); + String resvo = "result"; + String restype = ""; + String ebean = "ModelFacade"; + String bean = ebean.toLowerCase(); + Vector atts = uc.getParameters(); + Attribute res = uc.getResultParameter(); + + // String evocreate = createVOStatement(e,atts); + + out.println("import UIKit"); + out.println(); + out.println("class " + evc + " : UIViewController"); + out.println("{"); + out.println(" var " + bean + " : " + ebean + " = " + ebean + "()"); + + String parlist = ""; + for (int x = 0; x < atts.size(); x++) + { Attribute att = (Attribute) atts.get(x); + // if (att.isInputAttribute()) + out.println(" @IBOutlet weak var " + att + "Input: UITextField!"); + + parlist = parlist + att.getName(); + if (x < atts.size() - 1) + { parlist = parlist + ", "; } + } + + if (res != null) + { out.println(" @IBOutlet weak var " + ucname + "Output: UILabel!"); + restype = res.getType().getSwift(); + } + + out.println(" var userId : String = " + "\"0\""); + out.println(); + out.println(" override func viewDidLoad()"); + out.println(" { super.viewDidLoad()"); + // out.println(" self." + elist + " = " + bean + "." + getlist + "()"); + out.println(" }"); + out.println(""); + + String attdecoder = " guard "; + boolean previous = false; + String localVars = ""; + + for (int x = 0; x < atts.size(); x++) + { Attribute att = (Attribute) atts.get(x); + // if (att.isInputAttribute()) + { if (previous) + { attdecoder = attdecoder + ", "; } + attdecoder = attdecoder + " let " + att + " = " + + Expression.unwrapSwift(att + "Input.text",att.getType()); + previous = true; + } + // else + // { Type atype = att.getType(); + // if (atype != null) + // { localVars = localVars + " var " + att + " : " + atype.getSwift() + "\n"; } + // } + } + attdecoder = attdecoder + " else { return }\n"; + + String updateScreen = ""; + + // for (int x = 0; x < atts.size(); x++) + if (res != null) + { Attribute att = res; // (Attribute) atts.get(x); + // if (att.isOutput()) + { updateScreen = updateScreen + " " + att + "Output.text = String(" + att + ")"; + } + } + + // for (int y = 0; y < usecases.size(); y++) + // { UseCase uc = (UseCase) usecases.get(y); + // String ucname = uc.getName(); + out.println(" @IBAction func " + ucname + "(_ sender: Any) {"); + out.println(attdecoder); + // out.println(localVars); + // out.println(evocreate); + if (res != null) + { out.println(" var " + resvo + " : " + restype + " = " + bean + "." + ucname + "(" + parlist + ")"); + out.println(updateScreen); + } + else + { out.println(" " + bean + "." + ucname + "(" + parlist + ")"); } + out.println(" }"); + // } + + out.println(""); + + out.println(" override func didReceiveMemoryWarning()"); + out.println(" { super.didReceiveMemoryWarning() }"); + out.println(""); + out.println("}"); + } + + public void listViewController(Entity e, PrintWriter out) + { String ename = e.getName(); + String evc = "list" + ename + "Activity"; + String evo = ename + "VO"; + String ebean = "ModelFacade"; + String bean = "model"; + Vector atts = e.getAttributes(); + String elist = ename.toLowerCase() + "List"; + String getlist = "list" + ename; + + out.println("package com.example.app;"); + out.println(); + out.println("import android.os.Bundle;"); + out.println("import android.app.ListActivity;"); + out.println("import android.view.View;"); + out.println("import android.widget.ArrayAdapter;"); + out.println("import android.widget.ListView;"); + out.println("import android.widget.TextView;"); + out.println("import java.util.ArrayList;"); + out.println("import java.util.List;"); + out.println(); + out.println("public class " + evc + " extends ListActivity"); + out.println("{ private ModelFacade model;"); + out.println(); + out.println(" ArrayList<" + evo + "> " + elist + ";"); + out.println(); + out.println(" @Override"); + out.println(" protected void onCreate(Bundle savedInstanceState)"); + out.println(" { super.onCreate(savedInstanceState);"); + out.println(" setContentView(R.layout.list" + ename + "_layout);"); + out.println(" model = ModelFacade.getInstance(this);"); + out.println(" ArrayList itemList = model.stringList" + ename + "();"); + out.println(" ArrayAdapter adapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,itemList);"); + out.println(" setListAdapter(adapter);"); + out.println(" }"); + out.println(); + + out.println(" public void onListItemClick(ListView parent, View v, int position, long id)"); + out.println(" { model.setSelected" + ename + "(position); }"); + out.println(); + out.println("}"); + } + + public void androidDeleteViewActivity(String op, Entity ent, PrintWriter out) + { String ename = ent.getName(); + String fullop = op + ename; + String beanclass = ename + "Bean"; + String bean = beanclass.toLowerCase(); + String evo = ename + "VO"; + + out.println("package com.example.app;\n"); + out.println(); + out.println("import android.os.Bundle;"); + out.println("import android.app.Activity;"); + out.println("import android.view.View;"); + out.println("import android.util.Log;"); + out.println("import android.widget.EditText;\n\r"); + out.println(); + + out.println("public class View" + fullop + " extends Activity"); + out.println("{ " + beanclass + " " + bean + ";"); + out.println(" ModelFacade model = null;"); + out.println(); + + Vector pars = new Vector(); + Attribute pk = ent.getPrincipalPrimaryKey(); + if (pk == null) + { out.println("/* ERROR: no primary key for " + ename + " */"); + out.println("}"); + return; + } + String pkname = pk.getName(); + pars.add(pk); + + for (int x = 0; x < pars.size(); x++) + { Attribute par = (Attribute) pars.get(x); + String pnme = par.getName(); + String tfnme = pnme + "TextField"; + String dname = pnme + "Data"; + out.println(" EditText " + tfnme + ";"); + out.println(" String " + dname + " = \"\";"); + } + out.println(); + out.println(); + out.println(" @Override"); + out.println(" protected void onCreate(Bundle bundle)"); + out.println(" { super.onCreate(bundle);"); + out.println(" setContentView(R.layout." + fullop + "_layout);"); + + for (int x = 0; x < pars.size(); x++) + { Attribute par = (Attribute) pars.get(x); + String pnme = par.getName(); + String tfnme = pnme + "TextField"; + out.println(" " + tfnme + " = (EditText) findViewById(R.id." + fullop + pnme + ");"); + } + out.println(" " + bean + " = new " + beanclass + "(this);"); + out.println(" model = ModelFacade.getInstance(this);"); + out.println(" " + evo + " _current = model.getSelected" + ename + "();"); + out.println(" if (_current != null)"); + out.println(" { " + pkname + "TextField.setText(_current." + pkname + "); }"); + out.println(" }\n\r"); + out.println(); + + out.println(" public void " + fullop + "OK(View _v) "); + out.println(" {"); + for (int x = 0; x < pars.size(); x++) + { Attribute att = (Attribute) pars.get(x); + String aname = att.getName(); + String tfnme = aname + "TextField"; + String dname = aname + "Data"; + out.println(" " + dname + " = " + tfnme + ".getText() + \"\";"); + out.println(" " + bean + ".set" + aname + "(" + dname + ");"); + } + out.println(" if (" + bean + ".is" + fullop + "error())"); + out.println(" { Log.w(getClass().getName(), " + bean + ".errors()); }"); + out.println(" else"); + out.println(" { " + bean + "." + fullop + "(); }"); + + out.println(" }\n\r"); + out.println(); + + out.println(" public void " + fullop + "Cancel(View _v) {}"); + out.println("}"); + } + + public void androidEditViewActivity(String op, Entity ent, PrintWriter out) + { String ename = ent.getName(); + String fullop = op + ename; + String beanclass = ename + "Bean"; + String bean = beanclass.toLowerCase(); + String evo = ename + "VO"; + + out.println("package com.example.app;\n"); + out.println(); + out.println("import android.os.Bundle;"); + out.println("import android.app.Activity;"); + out.println("import android.view.View;"); + out.println("import android.util.Log;"); + out.println("import android.widget.EditText;\n\r"); + out.println(); + + out.println("public class View" + fullop + " extends Activity"); + out.println("{ " + beanclass + " " + bean + ";"); + out.println(" model : ModelFacade = null;"); + out.println(); + + Vector pars = ent.getAttributes(); + + for (int x = 0; x < pars.size(); x++) + { Attribute par = (Attribute) pars.get(x); + String pnme = par.getName(); + String tfnme = pnme + "TextField"; + String dname = pnme + "Data"; + out.println(" EditText " + tfnme + ";"); + out.println(" String " + dname + " = \"\";"); + } + out.println(); + out.println(); + out.println(" @Override"); + out.println(" protected void onCreate(Bundle bundle)"); + out.println(" { super.onCreate(bundle);"); + out.println(" setContentView(R.layout." + fullop + "_layout);"); + + for (int x = 0; x < pars.size(); x++) + { Attribute par = (Attribute) pars.get(x); + String pnme = par.getName(); + String tfnme = pnme + "TextField"; + out.println(" " + tfnme + " = (EditText) findViewById(R.id." + fullop + pnme + ");"); + } + out.println(" " + bean + " = new " + beanclass + "(this);"); + out.println(" model = ModelFacade.getInstance(this);"); + out.println(" " + evo + " _current = model.getSelected" + ename + "();"); + out.println(" if (_current != null)"); + out.println(" { "); + for (int x = 0; x < pars.size(); x++) + { Attribute par = (Attribute) pars.get(x); + String pnme = par.getName(); + String tfnme = pnme + "TextField"; + out.println(" " + tfnme + "TextField.setText(_current." + pnme + ");"); + } + out.println(" }"); + out.println(" }\n\r"); + out.println(); + + out.println(" public void " + fullop + "OK(View _v) "); + out.println(" {"); + for (int x = 0; x < pars.size(); x++) + { Attribute att = (Attribute) pars.get(x); + String aname = att.getName(); + String tfnme = aname + "TextField"; + String dname = aname + "Data"; + out.println(" " + dname + " = " + tfnme + ".getText() + \"\";"); + out.println(" " + bean + ".set" + aname + "(" + dname + ");"); + } + out.println(" if (" + bean + ".is" + fullop + "error())"); + out.println(" { Log.w(getClass().getName(), " + bean + ".errors()); }"); + out.println(" else"); + out.println(" { " + bean + "." + fullop + "(); }"); + + out.println(" }\n\r"); + out.println(); + + out.println(" public void " + fullop + "Cancel(View _v) {}"); + out.println("}"); + } + + public void generateManifest(String appname, PrintWriter out) + { out.println(""); + out.println(""); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(""); + } + +} diff --git a/AppGenerator.java b/AppGenerator.java new file mode 100644 index 00000000..bb4dba35 --- /dev/null +++ b/AppGenerator.java @@ -0,0 +1,14 @@ +import java.util.Vector; +import java.io.*; + + +public abstract class AppGenerator +{ + + public abstract void modelFacade(Vector usecases, CGSpec cgs, Vector entities, Vector types, PrintWriter out); + + public abstract void singlePageApp(UseCase uc, CGSpec cgs, PrintWriter out); + + public abstract void listViewController(Entity e, PrintWriter out); + +} diff --git a/Association.java b/Association.java index 74c6ed4f..ad12f846 100644 --- a/Association.java +++ b/Association.java @@ -36,13 +36,22 @@ public class Association extends ModelElement public Association(Entity e1, Entity e2, int c1, int c2, String r1, String r2) - { super(e1.getName() + "_" + e2.getName()); + { super(e1 + "_" + e2); + entity1 = e1; entity2 = e2; card1 = c1; card2 = c2; role1 = r1; role2 = r2; + if (e1 == null) + { System.err.println("!!! FATAL ERROR: null class at association end 1"); + return; + } + if (e2 == null) + { System.err.println("!!! FATAL ERROR: null class at association end 2"); + return; + } } public Association(Entity e1, Attribute att) diff --git a/AttEditDialog.java b/AttEditDialog.java index bf4ea968..7bf2e55d 100644 --- a/AttEditDialog.java +++ b/AttEditDialog.java @@ -100,7 +100,7 @@ class AttDialogPanel extends JPanel private JLabel initLabel; JTextField initField; /* initial value */ - JCheckBox senBox, intBox, actBox, derBox; + JCheckBox senBox, intBox, actBox, derBox, sumBox; private JPanel kindPanel; private ButtonGroup kindGroup; /* kind */ @@ -133,14 +133,16 @@ public AttDialogPanel() initField = new JTextField(); kindPanel = new JPanel(); - senBox = new JCheckBox("Sensor"); + senBox = new JCheckBox("Input"); intBox = new JCheckBox("Internal",true); - actBox = new JCheckBox("Actuator"); + actBox = new JCheckBox("Output"); derBox = new JCheckBox("Derived"); + sumBox = new JCheckBox("Summary"); kindPanel.add(senBox); kindPanel.add(intBox); kindPanel.add(actBox); kindPanel.add(derBox); + kindPanel.add(sumBox); kindPanel.setBorder( BorderFactory.createTitledBorder("Kind")); kindGroup = new ButtonGroup(); @@ -148,6 +150,7 @@ public AttDialogPanel() kindGroup.add(intBox); kindGroup.add(actBox); kindGroup.add(derBox); + kindGroup.add(sumBox); frozenPanel = new JPanel(); frozBox = new JCheckBox("Frozen"); @@ -225,6 +228,8 @@ else if (kind == ModelElement.ACT) { actBox.setSelected(true); } else if (kind == ModelElement.DERIVED) { derBox.setSelected(true); } + else if (kind == ModelElement.SUMMARY) + { sumBox.setSelected(true); } } public Dimension getPreferredSize() @@ -269,6 +274,8 @@ else if (dialogPanel.actBox.isSelected()) { kind = ModelElement.ACT; } else if (dialogPanel.derBox.isSelected()) { kind = ModelElement.DERIVED; } + else if (dialogPanel.sumBox.isSelected()) + { kind = ModelElement.SUMMARY; } else { kind = ModelElement.INTERNAL; } setFields(dialogPanel.nameField.getText(), diff --git a/Attribute.java b/Attribute.java index 7a661013..a23611b0 100644 --- a/Attribute.java +++ b/Attribute.java @@ -1,3 +1,4 @@ + import java.util.Vector; import java.io.*; @@ -49,6 +50,27 @@ else if ("Sequence".equals(tname)) { upper = 0; lower = 0; } } } + + public Attribute(String nme, Type t) + { this(nme,t,ModelElement.INTERNAL); } + + public Attribute(BasicExpression e) + { super(e.getData()); + type = e.getType(); + elementType = e.getElementType(); + entity = e.getEntity(); + int c2 = e.getMultiplicity(); + if (c2 == ModelElement.ONE) + { upper = 1; + lower = 1; + } + else + { upper = 0; + lower = 0; + } + kind = INTERNAL; + } + public Attribute(Association ast) { super(ast.getRole2()); @@ -121,6 +143,40 @@ else if ("target".equals(st)) } // and set the entity and name. Set it as aggregation if all // path elements are aggregations. Likewise for unique. + public boolean isNumeric() + { return type != null && type.isNumericType(); } + + public boolean isString() + { return type != null && type.isStringType(); } + + public boolean isCollection() + { return type != null && type.isCollectionType(); } + + public boolean isSet() + { return type != null && type.isSetType(); } + + public boolean isSequence() + { return type != null && type.isSequenceType(); } + + public boolean equalByNameAndOwner(Attribute att) + { if (att.getName().equals(name) && + att.getOwner() == entity && entity != null) + { return true; } + return false; + } + + public boolean equalToReverseDirection(Attribute att) + { if (att.getName().equals(role1 + "") && + elementType != null && elementType.isEntity() && + att.getOwner() == elementType.getEntity()) + { return true; } + else if (att.getName().equals(role1 + "") && + type != null && type.isEntity() && + att.getOwner() == type.getEntity()) + { return true; } + return false; + } + public Attribute objectReference() { // path omitting the final feature @@ -135,6 +191,59 @@ public Attribute objectReference() return new Attribute(pathprefix); } + public String cg(CGSpec cgs) + { String atext = this + ""; + Vector args = new Vector(); + args.add(getName()); + args.add(type.cg(cgs)); + Vector eargs = new Vector(); + eargs.add(this); + eargs.add(type); + // only one Attribute rule? + // maybe for static/frozen + CGRule r = cgs.matchedAttributeRule(this,atext); + if (r != null) + { return r.applyRule(args,eargs,cgs); } + return atext; + } + + public String cgReference(CGSpec cgs) + { String atext = this + ""; + Vector args = new Vector(); + args.add(getName()); + args.add(type.cg(cgs)); + Vector eargs = new Vector(); + eargs.add(this); + eargs.add(type); + + // only one Reference rule? + + CGRule r = cgs.matchedReferenceRule(this,atext); + if (r != null) + { return r.applyRule(args,eargs,cgs); } + return atext; + } + + public String cgParameter(CGSpec cgs, Vector partail) + { String atext = this + ""; + Vector args = new Vector(); + args.add(getName()); + args.add(type.cg(cgs)); + if (partail.size() == 0) + { args.add(""); } + else + { Attribute p = (Attribute) partail.get(0); + Vector newtail = new Vector(); + newtail.addAll(partail); + newtail.remove(0); + args.add(p.cgParameter(cgs,newtail)); + } + CGRule r = cgs.matchedParameterRule(this,partail,atext); + if (r != null) + { return r.applyRule(args); } + return atext; + } // but omit initialisations for parameters + public Type getReverseType() { if (entity != null) { Type et = new Type(entity); @@ -147,9 +256,26 @@ public Type getReverseType() return null; } + public Entity getClassType() + { if (type != null) + { if (type.isEntity()) + { return type.getEntity(); } + } + + if (elementType != null) + { if (elementType.isEntity()) + { return elementType.getEntity(); } + } + + return null; + } + public String getRole1() { return role1; } + public boolean hasOpposite() + { return role1 != null && role1.length() > 0; } + public Attribute getReverseReference() { if (role1 != null && role1.length() > 0) { Type tr = getReverseType(); @@ -167,7 +293,7 @@ public boolean isBidirectionalassociation() { return (role1 != null && role1.length() > 0); } public Expression makeInverseCallExpression() - { // E1.allInstances()->select( e1x � e1.att->includes(self)) for *-mult att + { // E1.allInstances()->select( e1x � e1.att->includes(self)) for *-mult att BasicExpression srcexp = new BasicExpression(this); srcexp.setUmlKind(Expression.ATTRIBUTE); @@ -214,9 +340,12 @@ public static boolean isMultipleValued(Vector path) public boolean isMultiValued() { return upper != 1; } + public boolean isMandatory() + { return lower > 0; } + public int upperBound() { if (upper == 0) - { return 1000000000; } + { return Integer.MAX_VALUE; } return upper; } @@ -389,11 +518,17 @@ public void replaceIntermediateEntity(Entity orig, Entity newe) } } - public Expression atlComposedExpression(String svar) - { if (navigation.size() <= 1) - { return new BasicExpression(svar + "." + this); } + public Expression atlComposedExpression(String svar, Attribute trg, Vector ems) + { Expression res = null; + + Entity sent = type.getEntity(); + if (sent == null && elementType != null) + { sent = elementType.getEntity(); } + + if (navigation.size() <= 1) + { res = new BasicExpression(svar + "." + this); } else - { Expression res = new BasicExpression(svar); + { res = new BasicExpression(svar); res.multiplicity = ModelElement.ONE; for (int i = 0; i < navigation.size(); i++) @@ -415,7 +550,101 @@ else if (res.multiplicity != ModelElement.ONE && att.upper != 1) res.multiplicity = ModelElement.MANY; } } - return res; + } + + if (trg.type.isEntityType()) + { Entity tent = trg.type.getEntity(); + EntityMatching em = ModelMatching.findEntityMatchingFor(sent,tent,ems); + if (em != null && em.isSecondary()) + { String trgvarname = em.realtrg.getName().toLowerCase() + "_x"; + return new BasicExpression("thisModule.resolveTemp(" + res + ", '" + trgvarname + "')"); + } + } + else if (Type.isEntityCollection(trg.type)) + { Entity tent = trg.elementType.getEntity(); + EntityMatching em = ModelMatching.findEntityMatchingFor(sent,tent,ems); + if (em != null && em.isSecondary()) + { String trgvarname = em.realtrg.getName().toLowerCase() + "_x"; + return new BasicExpression("thisModule.resolveTemp(" + res + ", '" + trgvarname + "')"); + } + } + return res; + } + + public Expression etlComposedExpression(String svar, Attribute trg, Vector ems) + { Entity sent = type.getEntity(); + if (sent == null && elementType != null) + { sent = elementType.getEntity(); } + + if (navigation.size() <= 1) + { if (trg.type.isEntityType()) + { Entity tent = trg.type.getEntity(); + EntityMatching em = ModelMatching.findEntityMatchingFor(sent,tent,ems); + if (em != null) + { return new BasicExpression(svar + "." + this + ".equivalent('" + em.realsrc + "2" + + em.realtrg + "')"); + } + return new BasicExpression(svar + "." + this + ".equivalent()"); + } + else if (Type.isEntityCollection(trg.type)) + { Entity tent = trg.elementType.getEntity(); + EntityMatching em = ModelMatching.findEntityMatchingFor(sent,tent,ems); + if (em != null) + { return new BasicExpression(svar + "." + this + ".equivalent('" + em.realsrc + "2" + + em.realtrg + "')"); + } + return new BasicExpression(svar + "." + this + ".equivalent()"); + } + else + { return new BasicExpression(svar + "." + this); } + } + else + { Expression res = new BasicExpression(svar); + res.multiplicity = ModelElement.ONE; + + for (int i = 0; i < navigation.size(); i++) + { Attribute att = (Attribute) navigation.get(i); + if (res.multiplicity == ModelElement.ONE) + { BasicExpression r = new BasicExpression(att); + r.setObjectRef(res); + res = r; + // res.multiplicity = ModelElement.ONE; + } + else if (res.multiplicity != ModelElement.ONE && att.upper == 1) + { // Expression ce = new BinaryExpression("->collect",res,new BasicExpression(att)); + // res = ce; + // res.multiplicity = ModelElement.MANY; + BasicExpression r = new BasicExpression(att); + r.setObjectRef(res); + res = r; + } + else if (res.multiplicity != ModelElement.ONE && att.upper != 1) + { Expression ce = new BinaryExpression("->collect",res,new BasicExpression(att)); + res = new UnaryExpression("->flatten",ce); + res.multiplicity = ModelElement.MANY; + } + } + + if (trg.type.isEntityType()) + { Entity tent = trg.type.getEntity(); + EntityMatching em = ModelMatching.findEntityMatchingFor(sent,tent,ems); + if (em != null) + { return new BasicExpression(res + ".equivalent('" + em.realsrc + "2" + + em.realtrg + "')"); + } + return new BasicExpression(res + ".equivalent()"); + } + else if (Type.isEntityCollection(trg.type)) + { Entity tent = trg.elementType.getEntity(); + EntityMatching em = ModelMatching.findEntityMatchingFor(sent,tent,ems); + if (em != null) + { return new BasicExpression(res + ".equivalent('" + em.realsrc + "2" + + em.realtrg + "')"); + } + return new BasicExpression(res + ".equivalent()"); + } + else + { return res; } } } @@ -603,6 +832,15 @@ public void setUnique(boolean uniq) { card1 = ModelElement.ZEROONE; } } + public boolean isOutput() + { return hasStereotype("output"); } + + public boolean isInputAttribute() + { return hasStereotype("input"); } + + public boolean isSummary() + { return kind == ModelElement.SUMMARY; } + public void setIdentity(boolean uniq) { unique = uniq; if (uniq) @@ -615,9 +853,45 @@ public boolean isIdentity() public boolean isIdentityFeature() { return card1 == ModelElement.ZEROONE; } + public boolean isPrimaryAttribute() + { // The first identity attribute in its owner's attributes + + if (isIdentity()) { } + else + { return false; } + + Entity own = getOwner(); + if (own == null) + { return false; } + + Vector atts = own.getAttributes(); + for (int i = 0; i < atts.size(); i++) + { Attribute att = (Attribute) atts.get(i); + if (att.isIdentity()) + { if (att == this) + { return true; } + return false; + } + } + return false; + } public void setFrozen(boolean fr) - { frozen = fr; } + { frozen = fr; + if (fr) + { addStereotype("readOnly"); } + else + { removeStereotype("readOnly"); } + } + + public boolean isInt() + { return type != null && type.getName().equals("int"); } + + public boolean isLong() + { return type != null && type.getName().equals("long"); } + + public boolean isDouble() + { return type != null && type.getName().equals("double"); } public boolean isFinal() { return frozen && initialExpression != null; } @@ -3342,22 +3616,23 @@ else if ("boolean".equals(tname)) { return tname; } } -public String androidExtractOp() +public String androidExtractOp(String ent) { String allcaps = name.toUpperCase(); + String tname = type.getName(); if ("String".equals(tname)) - { return "cursor.getString(COL_" + allcaps + ")"; } + { return "cursor.getString(" + ent + "_COL_" + allcaps + ")"; } if ("int".equals(tname)) - { return "cursor.getInt(COL_" + allcaps + ")"; } + { return "cursor.getInt(" + ent + "_COL_" + allcaps + ")"; } if ("long".equals(tname)) - { return "cursor.getLong(COL_" + allcaps + ")"; } + { return "cursor.getLong(" + ent + "_COL_" + allcaps + ")"; } if ("double".equals(tname)) - { return "cursor.getDouble(COL_" + allcaps + ")"; } + { return "cursor.getDouble(" + ent + "_COL_" + allcaps + ")"; } else - { return "cursor.getString(COL_" + allcaps + ")"; } + { return "cursor.getString(" + ent + "_COL_" + allcaps + ")"; } } - public String androidExtractOp(String resultSet) +/* public String androidExtractOp(String resultSet) { String res = resultSet + ".get"; String tname = type.getName(); if (tname.equals("int")) @@ -3368,7 +3643,7 @@ else if (tname.equals("double")) { res = res + "String(\""; } res = res + getName() + "\")"; return res; - } + } */ public String ejbBeanGet() { String nme = getName(); @@ -3981,9 +4256,8 @@ else if ("double".equals(t)) } else if ("String".equals(t)) { res.add(nme + " = \"\""); - res.add(nme + " = \" abc \""); - res.add(nme + " = \"_XY Z \""); - res.add(nme + " = \"#�$* &~@':\""); + res.add(nme + " = \" abc_XZ \""); + res.add(nme + " = \"#�$* &~@':\""); } else if (vs != null && vs.size() > 0) { String v0 = (String) vs.get(0); @@ -4035,7 +4309,7 @@ public String androidTableEntryField(String ent, String op) { String nme = getName(); String label = Named.capitalise(nme); String attfield = op + ent + nme; - String attlabel = op + ent+ label; + String attlabel = op + ent + nme + "Label"; String hint = ent + " " + nme; String res1 = " \n\r"; String res2 = ""; - if (isIdentity()) - { res2 = " \n\r"; + // } + // else + if (isNumeric()) + { res2 = " \n\r"; } - else + else { res2 = " \n\r"; diff --git a/AttributeMatching.java b/AttributeMatching.java index af98f1ce..fbe47f47 100644 --- a/AttributeMatching.java +++ b/AttributeMatching.java @@ -1,7 +1,9 @@ -import java.util.Vector; import java.io.*; import java.util.Collections; import javax.swing.JOptionPane; +import java.util.Vector; +import java.util.List; + /****************************** * Copyright (c) 2003,2019 Kevin Lano @@ -58,6 +60,42 @@ public AttributeMatching(Expression source, Attribute target, Attribute var, auxVariables = auxvars; } + public AttributeMatching(Expression source, Expression target) + { src = new Attribute("" + source, source.getType(), + ModelElement.INTERNAL); + src.setElementType(source.getElementType()); + + + srcvalue = source; + trg = new Attribute("" + target, target.getType(), + ModelElement.INTERNAL); + trg.setElementType(target.getElementType()); + + srcname = srcvalue + ""; + trgname = trg.getName(); + } + + public void setElementVariable(Attribute var) + { elementVariable = var; } + + public void addAuxVariable(Attribute var) + { if (auxVariables.contains(var)) { } + else + { auxVariables.add(var); } + } + + public void setExpressionMatch(Expression source, Attribute target, Attribute var) + { src = new Attribute("" + source, source.getType(), ModelElement.INTERNAL); + src.setType(source.getType()); + src.setElementType(source.getElementType()); + + srcvalue = source; + trg = target; + elementVariable = var; + srcname = srcvalue + ""; + trgname = trg.getName(); + } + public Attribute getSource() { return src; } @@ -67,6 +105,203 @@ public Attribute getTarget() public String toString() { return " " + srcname + " |--> " + trgname; } + boolean isDirect() // either source or target is a direct attribute + { if (src.getNavigation().size() <= 1) + { return true; } + if (trg.getNavigation().size() <= 1) + { return true; } + return false; + } + + boolean isDirectSource() // source is a direct attribute + { if (src.getNavigation().size() <= 1) + { return true; } + return false; + } + + boolean isDirectTarget() // target is a direct attribute + { if (trg.getNavigation().size() <= 1) + { return true; } + return false; + } + + boolean isValueAssignment() + { return srcvalue != null && elementVariable == null; } + + boolean isExpressionAssignment() + { return srcvalue != null && elementVariable != null; } + + boolean isStringAssignment() + { return srcvalue != null && auxVariables.size() > 1; } + // But could occur even if srcvalue is not a string. + + boolean isValueTyped() + { // target and source are of a value type + Type st = src.getType(); + Type tt = trg.getType(); + if (Type.isValueType(st) && Type.isValueType(tt)) + { return true; } + return false; + } + + boolean isPossibleFeatureMerge() + { // of form s->before(sep) or s->after(sep), etc + if (srcvalue != null && + (srcvalue instanceof BinaryExpression)) + { BinaryExpression be = (BinaryExpression) srcvalue; + if ("->before".equals(be.operator) || "->after".equals(be.operator)) + { return true; } + if ("->front".equals(be.operator) || "->last".equals(be.operator)) + { return true; } + if ("->first".equals(be.operator) || "->tail".equals(be.operator)) + { return true; } + } + return false; + } + + Vector findMergeFamily(Vector ams, Vector seen) + { // of form s->before(sep) or s->after(sep), etc + Vector res = new Vector(); + res.add(this); + + if (srcvalue != null && + (srcvalue instanceof BinaryExpression)) + { BinaryExpression be = (BinaryExpression) srcvalue; + if ("->before".equals(be.operator)) + { Expression sep = be.getRight(); + for (int i = 0; i < ams.size(); i++) + { AttributeMatching amx = (AttributeMatching) ams.get(i); + if (amx.isExpressionAssignment() && !(seen.contains(amx)) && + amx.srcvalue instanceof BinaryExpression) + { BinaryExpression be2 = (BinaryExpression) amx.srcvalue; + if ("->after".equals(be2.getOperator()) && + (sep + "").equals(be2.getRight() + "") && + (be.getLeft() + "").equals(be2.getLeft() + "")) + { res.add(amx); + return res; + } + } + } + } + else if ("->after".equals(be.operator)) + { Expression sep = be.getRight(); + for (int i = 0; i < ams.size(); i++) + { AttributeMatching amx = (AttributeMatching) ams.get(i); + if (amx.isExpressionAssignment() && !(seen.contains(amx)) && + amx.srcvalue instanceof BinaryExpression) + { BinaryExpression be2 = (BinaryExpression) amx.srcvalue; + if ("->before".equals(be2.getOperator()) && + (sep + "").equals(be2.getRight() + "") && + (be.getLeft() + "").equals(be2.getLeft() + "")) + { res.add(amx); + return res; + } + } + } + } + } + return res; + } + + Vector findMergeFamilySequence1(Vector ams, Vector seen) + { // of form s->front() or s->last(), etc + Vector res = new Vector(); + res.add(this); + + if (srcvalue != null && + (srcvalue instanceof UnaryExpression)) + { UnaryExpression be = (UnaryExpression) srcvalue; + if ("->front".equals(be.operator)) + { for (int i = 0; i < ams.size(); i++) + { AttributeMatching amx = (AttributeMatching) ams.get(i); + if (amx.isExpressionAssignment() && !(seen.contains(amx)) && + amx.srcvalue instanceof UnaryExpression) + { UnaryExpression be2 = (UnaryExpression) amx.srcvalue; + if ("->last".equals(be2.getOperator()) && + (be.getArgument() + "").equals(be2.getArgument() + "")) + { res.add(amx); + return res; + } + } + } + } + else if ("->last".equals(be.operator)) + { for (int i = 0; i < ams.size(); i++) + { AttributeMatching amx = (AttributeMatching) ams.get(i); + if (amx.isExpressionAssignment() && !(seen.contains(amx)) && + amx.srcvalue instanceof UnaryExpression) + { UnaryExpression be2 = (UnaryExpression) amx.srcvalue; + if ("->front".equals(be2.getOperator()) && + (be.getArgument() + "").equals(be2.getArgument() + "")) + { res.add(amx); + return res; + } + } + } + } + } + return res; + } + + Vector findMergeFamilySequence2(Vector ams, Vector seen) + { // of form s->tail() or s->first(), etc + Vector res = new Vector(); + res.add(this); + + if (srcvalue != null && + (srcvalue instanceof UnaryExpression)) + { UnaryExpression be = (UnaryExpression) srcvalue; + if ("->first".equals(be.operator)) + { for (int i = 0; i < ams.size(); i++) + { AttributeMatching amx = (AttributeMatching) ams.get(i); + if (amx.isExpressionAssignment() && !(seen.contains(amx)) && + amx.srcvalue instanceof UnaryExpression) + { UnaryExpression be2 = (UnaryExpression) amx.srcvalue; + if ("->tail".equals(be2.getOperator()) && + (be.getArgument() + "").equals(be2.getArgument() + "")) + { res.add(amx); + return res; + } + } + } + } + else if ("->tail".equals(be.operator)) + { for (int i = 0; i < ams.size(); i++) + { AttributeMatching amx = (AttributeMatching) ams.get(i); + if (amx.isExpressionAssignment() && !(seen.contains(amx)) && + amx.srcvalue instanceof UnaryExpression) + { UnaryExpression be2 = (UnaryExpression) amx.srcvalue; + if ("->first".equals(be2.getOperator()) && + (be.getArgument() + "").equals(be2.getArgument() + "")) + { res.add(amx); + return res; + } + } + } + } + } + return res; + } + + public boolean usedAsIntermediateClass(Entity e) + { // E is the entity element type of some p : trg.path + if (e == null) + { return false; } + + String nme = e.getName(); + + if (trg.isComposed()) + { Vector path = trg.getNavigation(); + for (int i = 0; i < path.size() - 1; i++) + { Attribute p = (Attribute) path.get(i); + if ((p.getElementType() + "").equals(nme)) + { return true; } + } + } + return false; + } + + public boolean unusedInSource(Attribute v) { String nme = v.getName(); @@ -91,14 +326,38 @@ public boolean unusedInSource(Attribute v) return true; } + public boolean usedInSource(Attribute v) + { if (v == src || v.equalByNameAndOwner(src) || v.equalToReverseDirection(src)) + { return true; } + + if (src.isComposed()) + { Vector path = src.getNavigation(); + for (int i = 0; i < path.size(); i++) + { Attribute p = (Attribute) path.get(i); + if (v == p || v.equalByNameAndOwner(p)) + { return true; } + } + return false; + } + + String nme = v.getName(); + + if (srcvalue != null) + { if (srcvalue.hasVariable(nme)) + { return true; } + } + + return false; + } // or src is the reverse + public double similarity(Map mm, Vector entities, Vector thesaurus) { // NMS similarity between src and trg double namesim = ModelElement.similarity(srcname, trgname); double namesemsim = Entity.nmsSimilarity(srcname, trgname, thesaurus); - double nsim = (namesim + namesemsim - namesim*namesemsim); + double nsim = (namesim + 2*namesemsim - namesim*namesemsim); double tsim = Attribute.partialTypeMatch(src,trg,mm,entities); return nsim*tsim; - } + } // should be namesemsim not 2*namesemsim public Vector enumConversions() { // Conversions from one enum type to a different one @@ -170,18 +429,41 @@ public boolean isBidirectionalassociationMatching() trg.isBidirectionalassociation(); } - public void addAuxVariable(Attribute x) - { auxVariables.add(x); } - public Vector inverts(Entity srcent, Entity trgent, Vector ems) { Vector res = new Vector(); if (isStringAssignment()) { // assume auxVariables.size() == 2 - BasicExpression delim = new BasicExpression("\"~\""); + // v1 + " ~ " + v2 --> v inverts as + // v->before(" ~ ") --> v1, v->after(" ~ ") --> v2 + + BasicExpression delim = new BasicExpression("\" ~ \""); + if (srcvalue instanceof BinaryExpression && auxVariables.size() >= 2) + { BinaryExpression sbe = (BinaryExpression) srcvalue; + if ("+".equals(sbe.operator)) + { Expression lbe = sbe.getLeft(); + Expression rbe = sbe.getRight(); + Attribute var1 = (Attribute) auxVariables.get(0); + Attribute var2 = (Attribute) auxVariables.get(1); + if ((rbe + "").equals(var1.getName()) && + rbe instanceof BinaryExpression) // var1 + (sep + var2) + { delim = (BasicExpression) ((BinaryExpression) rbe).getLeft(); + System.out.println(">> Delimiter = " + delim); + } + else if (lbe instanceof BinaryExpression && + (((BinaryExpression) lbe).getLeft() + "").equals(var1.getName())) + { // (var1 + sep) + var2 + delim = (BasicExpression) ((BinaryExpression) lbe).getRight(); + System.out.println(">> Delimiter = " + delim); + } + } + } + + delim.setType(new Type("String",null)); delim.setElementType(new Type("String",null)); BasicExpression etrg = new BasicExpression(trg); + etrg.setUmlKind(Expression.ATTRIBUTE); BinaryExpression be1 = new BinaryExpression("->before", etrg, delim); BinaryExpression be2 = new BinaryExpression("->after", etrg, delim); @@ -197,7 +479,10 @@ public Vector inverts(Entity srcent, Entity trgent, Vector ems) return res; } // In general could be several of these. else if (isExpressionAssignment()) - { if (srcvalue instanceof SetExpression) + { if ("self".equals(srcvalue + "")) + { return null; } // inverted to condition instead + + if (srcvalue instanceof SetExpression) { SetExpression sse = (SetExpression) srcvalue; if (sse.isOrdered() && sse.size() >= 2 && trg.isOrdered()) { // Sequence{r1,...,rn} --> trg inverts to trg->at(1) --> r1, ..., @@ -208,6 +493,9 @@ else if (isExpressionAssignment()) ModelElement.INTERNAL); Attribute a2 = new Attribute(v2 + "",v2.getType(), ModelElement.INTERNAL); + a1.setElementType(v1.getElementType()); + a2.setElementType(v2.getElementType()); + BasicExpression ind1 = new BasicExpression(1); BasicExpression ind2 = new BasicExpression(2); BasicExpression trge = new BasicExpression(trg); @@ -242,6 +530,9 @@ else if (isExpressionAssignment()) ModelElement.INTERNAL); Attribute a2 = new Attribute(rgt.data,rgt.getType(), ModelElement.INTERNAL); + a1.setElementType(lft.getElementType()); + a2.setElementType(rgt.getElementType()); + Expression trge = new BasicExpression(trg); UnaryExpression at1 = new UnaryExpression("->front",trge); UnaryExpression at2 = new UnaryExpression("->last",trge); @@ -296,6 +587,8 @@ else if (isExpressionAssignment()) { Entity b = etval.getEntity(); Entity b1 = trg.getElementType().getEntity(); BasicExpression selfexp = new BasicExpression("self"); + // selfexp.setUmlkind(Expression.VARIABLE); + selfexp.setType(new Type(b1)); selfexp.setElementType(new Type(b1)); @@ -315,6 +608,129 @@ else if (isExpressionAssignment()) return null; } } + } + + if (srcvalue instanceof BinaryExpression) + { BinaryExpression sbe = (BinaryExpression) srcvalue; + // elems->closure(next) --> parts for ordered parts inverts as + // parts --> elems, next computation of parts/container --> next + + // System.out.println("INVERSE OF: " + srcvalue + " --> " + trg); + // System.out.println(trg.isOrdered() + " " + trg.hasOpposite() + " " + + // ((BasicExpression) sbe.right).variable + " " + + // ((BasicExpression) sbe.right).isZeroOneRole()); + + if (sbe.operator.equals("->closure") && trg.isOrdered() && + sbe.left instanceof BasicExpression && trg.hasOpposite() && + sbe.right instanceof BasicExpression && + ((BasicExpression) sbe.right).variable != null && + ((BasicExpression) sbe.right).isZeroOneRole()) + { BasicExpression lft = (BasicExpression) sbe.left; + BasicExpression rgt = (BasicExpression) sbe.right; + String role1 = trg.getRole1(); // container + Attribute newrhs1 = new Attribute(sbe.left + "", sbe.left.getType(), + ModelElement.INTERNAL); // elems + newrhs1.setElementType(sbe.left.getElementType()); + AttributeMatching newam = new AttributeMatching(trg,newrhs1); + res.add(newam); + + Type targetref = src.getElementType(); + if (targetref != null && targetref.isEntity()) + { Entity trgref = targetref.getEntity(); + BasicExpression ownerparts = new BasicExpression(trg); + BasicExpression ownr = new BasicExpression(role1); + ownerparts.setUmlKind(Expression.ATTRIBUTE); + ownr.setUmlKind(Expression.ATTRIBUTE); + ownerparts.setObjectRef(ownr); + BasicExpression selfexp = new BasicExpression("self"); + // should have umlkind = VARIABLE + + selfexp.setType(new Type(trgref)); + selfexp.setElementType(new Type(trgref)); + BinaryExpression selfindex = new BinaryExpression("->indexOf", ownerparts, selfexp); + UnaryExpression ownerpartssize = new UnaryExpression("->size",ownerparts); + BinaryExpression test = new BinaryExpression("<", selfindex, ownerpartssize); + BinaryExpression nextindex = new BinaryExpression("+",selfindex,new BasicExpression(1)); + BinaryExpression ownerpartsat = new BinaryExpression("->at", ownerparts, nextindex); + SetExpression emptyset = new SetExpression(); + SetExpression nextset = new SetExpression(); + nextset.addElement(ownerpartsat); + ConditionalExpression newlhs = new ConditionalExpression(test,nextset,emptyset); + Type sourceref = trg.getElementType(); + if (sourceref != null && sourceref.isEntity()) + { Entity srcref = sourceref.getEntity(); + Type restype = new Type("Set", null); + restype.setElementType(new Type(srcref)); // not trgref + ownerparts.setType(restype); + ownerparts.setElementType(new Type(srcref)); + + newlhs.setType(restype); + newlhs.setElementType(new Type(srcref)); + newlhs.setBrackets(true); + + AttributeMatching newatm = + new AttributeMatching(newlhs,rgt.variable); + Attribute varnew = new Attribute(Identifier.nextIdentifier("var$"), + newlhs.getElementType(), + ModelElement.INTERNAL); + varnew.setElementType(newlhs.getElementType()); + newatm.setElementVariable(varnew); + + EntityMatching bb1 = ModelMatching.getRealEntityMatching(srcref,trgref,ems); + if (bb1 != null) + { bb1.addAttributeMatch(newatm); } + } + } + + return res; + } + else if (sbe.operator.equals("->unionAll") && sbe.right instanceof BasicExpression && + sbe.left instanceof BinaryExpression && + ((BinaryExpression) sbe.left).operator.equals("->closure")) + { BinaryExpression clsre = (BinaryExpression) sbe.left; + BasicExpression f = (BasicExpression) sbe.right; + Expression g = clsre.right; + BasicExpression r = new BasicExpression(trg); + Type Rtype = r.getElementType(); + BasicExpression Fclass = new BasicExpression(trgent); + Type Ftype = new Type(trgent); + String avalue = Identifier.nextIdentifier("var$"); + BasicExpression ax = new BasicExpression(avalue); + ax.setType(Ftype); + ax.setElementType(Ftype); + BinaryExpression aInFclass = new BinaryExpression(":", ax, Fclass); + BasicExpression ar = new BasicExpression(trg); + ar.setObjectRef(ax); + BinaryExpression aAncestor = new BinaryExpression("->includesAll", r, ar); + BinaryExpression aStrict = new BinaryExpression("/=", r, ar); + BinaryExpression aStrictAncestor = new BinaryExpression("&",aAncestor,aStrict); + BinaryExpression ancestors = new BinaryExpression("|", aInFclass, aStrictAncestor); + // ancestors->selectMaximals(r.size) |--> g + // r - ancestors->unionAll(r) |--> f + UnaryExpression rsize = new UnaryExpression("->size", r); + BinaryExpression lhsgmap = new BinaryExpression("->selectMaximals", ancestors, rsize); + Type FSetType = new Type("Set",null); + FSetType.setElementType(Ftype); + lhsgmap.setType(FSetType); + lhsgmap.setElementType(Ftype); + AttributeMatching gmatch = new AttributeMatching(lhsgmap,g); + Attribute gmatchvar = new Attribute(Identifier.nextIdentifier("var$"), Ftype, ModelElement.INTERNAL); + gmatchvar.setElementType(Ftype); + gmatch.setElementVariable(gmatchvar); + res.add(gmatch); + BinaryExpression ancestorsUnionAllr = new BinaryExpression("->unionAll", ancestors, r); + BinaryExpression fmatchlhs = new BinaryExpression("-", r, ancestorsUnionAllr); + Type FRefSetType = new Type("Set",null); + FRefSetType.setElementType(Rtype); + fmatchlhs.setType(FRefSetType); + fmatchlhs.setElementType(Rtype); + AttributeMatching fmatch = new AttributeMatching(fmatchlhs,f); + Attribute fmatchvar = new Attribute(Identifier.nextIdentifier("var$"), Rtype, ModelElement.INTERNAL); + fmatchvar.setElementType(Rtype); + fmatch.setElementVariable(fmatchvar); + res.add(fmatch); + return res; + } } } @@ -327,36 +743,89 @@ public AttributeMatching invert() { return new AttributeMatching(trg,src); } // ignores any expression/value match - boolean isDirect() // either source or target is a direct attribute - { if (src.getNavigation().size() <= 1) - { return true; } - if (trg.getNavigation().size() <= 1) - { return true; } - return false; - } - - boolean isDirectSource() // source is a direct attribute - { if (src.getNavigation().size() <= 1) - { return true; } - return false; - } - - boolean isDirectTarget() // target is a direct attribute - { if (trg.getNavigation().size() <= 1) - { return true; } - return false; - } - - boolean isValueAssignment() - { return srcvalue != null && elementVariable == null; } - - boolean isExpressionAssignment() - { return srcvalue != null && elementVariable != null; } - - boolean isStringAssignment() - { return srcvalue != null && auxVariables.size() > 1; } - // But could occur even if srcvalue is not a string. - + public static Vector invertCondition(Expression cond, Entity realsrc, Entity realtrg) + { Vector res = new Vector(); + if (cond instanceof BinaryExpression) + { BinaryExpression condbe = (BinaryExpression) cond; + + if (condbe.operator.equals("=")) + { // feature = value inverts as value --> feature + if ((condbe.left.umlkind == Expression.VARIABLE || + condbe.left.umlkind == Expression.ATTRIBUTE) && + condbe.left instanceof BasicExpression && + ((BasicExpression) condbe.left).variable != null && + condbe.right.umlkind != Expression.VARIABLE && + condbe.right.umlkind != Expression.ATTRIBUTE) + { Attribute trgfeature = ((BasicExpression) condbe.left).variable; + Attribute var = null; + + // System.out.println(">> Target feature is " + trgfeature + + // " " + trgfeature.getType()); + Expression newleft = null; + if ((condbe.right + "").equals("self")) + { newleft = new BasicExpression("self"); + newleft.setType(new Type(realtrg)); + newleft.setElementType(new Type(realtrg)); + var = new Attribute("self", + new Type(realtrg), + ModelElement.INTERNAL); + var.setElementType(new Type(realtrg)); + } + else + { newleft = condbe.right; + var = new Attribute(Identifier.nextIdentifier("var$"), + condbe.right.getType(), + ModelElement.INTERNAL); + var.setElementType(condbe.right.getElementType()); + } + AttributeMatching newam = new AttributeMatching(newleft,trgfeature); + newam.setElementVariable(var); + res.add(newam); + } + else if ((condbe.right.umlkind == Expression.VARIABLE || + condbe.right.umlkind == Expression.ATTRIBUTE) && + condbe.right instanceof BasicExpression && + ((BasicExpression) condbe.right).variable != null && + condbe.left.umlkind != Expression.VARIABLE && + condbe.left.umlkind != Expression.ATTRIBUTE) + { Attribute trgfeature = ((BasicExpression) condbe.right).variable; + Attribute var = null; + + // System.out.println(">> Target feature is " + trgfeature + + // " " + trgfeature.getType()); + // trgfeature.setUmlKind(Expression.ATTRIBUTE); + Expression newleft = null; + if ((condbe.left + "").equals("self")) + { newleft = new BasicExpression("self"); + newleft.setType(new Type(realtrg)); + newleft.setElementType(new Type(realtrg)); + var = new Attribute("self", + new Type(realtrg), + ModelElement.INTERNAL); + var.setElementType(new Type(realtrg)); + } + else + { newleft = condbe.left; + var = new Attribute(Identifier.nextIdentifier("var$"), + condbe.left.getType(), + ModelElement.INTERNAL); + var.setElementType(condbe.left.getElementType()); + } + AttributeMatching newam = new AttributeMatching(newleft,trgfeature); + newam.setElementVariable(var); + res.add(newam); + } + } + else if (condbe.operator.equals("&")) + { Expression cond1 = condbe.left; + Expression cond2 = condbe.right; + res.addAll(invertCondition(cond1,realsrc,realtrg)); + res.addAll(invertCondition(cond2,realsrc,realtrg)); + } + } + return res; + } // cases of f->includes(self) + Expression addReference(BasicExpression ref, Type t) { if (srcvalue != null) { return srcvalue.addReference(ref,t); } @@ -392,6 +861,8 @@ static Expression dataConversion(String language, Expression sexp, Type stype, T Type selemt = stype.getElementType(); Type telemt = ttype.getElementType(); + // In the case of entity types, (selemt.entity, telemt.entity) : mymap + if (("" + selemt).equals("" + telemt)) { if (sname.equals("Sequence") && tname.equals("Set")) { UnaryExpression res = new UnaryExpression("->asSet", sexp); @@ -482,11 +953,18 @@ else if (ttype.isCollectionType() && !stype.isCollectionType()) return res; } + if (stype.isCollectionType()) + { return sexp; } + + if (ttype.isCollectionType()) + { return sexp; } + return new BinaryExpression("->oclAsType", sexp, new BasicExpression(ttype)); } public Vector analyseCorrelationPatterns(Entity s, Entity t, Entity realsrc, Entity realtrg, - EntityMatching ematch, Vector ems) + EntityMatching ematch, Vector ems, ModelMatching modmatch, + Vector entities) { Vector res = new Vector(); if (src.isComposition() && !trg.isComposition()) @@ -531,8 +1009,8 @@ public Vector analyseCorrelationPatterns(Entity s, Entity t, Entity realsrc, Ent if (trgunused.size() > 0) { System.out.println(">>! Recommend: " + trgunused + "\n"); } String ans = - JOptionPane.showInputDialog("Replace " + trgent + " by? (y/n):"); - if (ans != null && "y".equals(ans)) + JOptionPane.showInputDialog("Replace " + trgent + " by? (name/null):"); + if (ans != null && !("null".equals(ans))) { Entity conc = (Entity) ModelElement.lookupByName(ans,trgactualleaves); if (conc != null) { trg.replaceIntermediateEntity(trgent,conc); } @@ -763,24 +1241,9 @@ else if (mult1 == ModelElement.MANY && mult2 == ModelElement.ONE) // Suggest a source splitting if possible. Entity realtrgsup = realtrg.getSuperclass(); if (realtrgsup != null) - { Vector siblings = new Vector(); - siblings.addAll(realtrgsup.getSubclasses()); - siblings.remove(realtrg); - if (siblings.size() == 1) - { UnaryExpression srcsize = new UnaryExpression("->size",new BasicExpression(src)); - Expression guard0 = new BinaryExpression("=",srcsize,new BasicExpression(1)); - Expression guard1 = new BinaryExpression("/=",srcsize,new BasicExpression(1)); - ematch.addCondition(guard0); - Entity othere = (Entity) siblings.get(0); - EntityMatching newothermatch = new EntityMatching(realsrc,othere); - newothermatch.addCondition(guard1); - newothermatch.copyApplicableAttributeMappings(ematch.attributeMappings); - System.out.println(">>> Suggest new Entity match: " + newothermatch); - String ans = - JOptionPane.showInputDialog("Add to entity matches?: (y/n) "); - if (ans != null && "y".equals(ans)) - { ems.add(newothermatch); } - } + { optionalToTotal(realtrgsup, realsrc, realtrg, + ematch, entities, + modmatch, res); } q.addSourceEntity(realsrc); @@ -796,7 +1259,16 @@ else if (mult1 == ModelElement.ONE && src.getLower() == 0 && mult2 == ModelEleme "Feature " + realsrc + "::" + src + " narrowed from 0..1 to ONE multiplicity in " + realtrg + "::" + trg); - q.addSourceEntity(realsrc); + + // Suggest a source splitting if possible. + Entity realtrgsup = realtrg.getSuperclass(); + if (realtrgsup != null) + { optionalToTotal(realtrgsup, realsrc, realtrg, + ematch, entities, + modmatch, res); + } + + q.addSourceEntity(realsrc); q.addTargetEntity(realtrg); q.addSourceFeature(src); q.addTargetFeature(trg); @@ -844,7 +1316,16 @@ else if (mult1 == ModelElement.MANY && src.getUpper() == 1 && mult2 == ModelElem "Feature " + realsrc + "::" + src + " narrowed from 0..1 to 1 multiplicity in " + realtrg + "::" + trg); - q.addSourceEntity(realsrc); + + // Suggest a source splitting if possible. + Entity realtrgsup = realtrg.getSuperclass(); + if (realtrgsup != null) + { optionalToTotal(realtrgsup, realsrc, realtrg, + ematch, entities, + modmatch, res); + } + + q.addSourceEntity(realsrc); q.addTargetEntity(realtrg); q.addSourceFeature(src); q.addTargetFeature(trg); @@ -856,6 +1337,40 @@ else if (mult1 == ModelElement.MANY && src.getUpper() == 1 && mult2 == ModelElem return res; } // also feature merging; stereotype changes + private void optionalToTotal(Entity realtrgsup, Entity realsrc, Entity realtrg, + EntityMatching ematch, Vector entities, + ModelMatching modmatch, Vector res) + { Vector siblings = new Vector(); + siblings.addAll(realtrgsup.getSubclasses()); + siblings.remove(realtrg); + if (siblings.size() == 1) + { UnaryExpression srcsize = new UnaryExpression("->size",new BasicExpression(src)); + Expression guard0 = new BinaryExpression("=",srcsize,new BasicExpression(1)); + Expression guard1 = new BinaryExpression("/=",srcsize,new BasicExpression(1)); + Entity othere = (Entity) siblings.get(0); + EntityMatching newothermatch = new EntityMatching(realsrc,othere); + newothermatch.addCondition(guard1); + newothermatch.copyApplicableAttributeMappings(ematch.attributeMappings); + System.out.println(">>> Suggest splitting based on cases of " + src + + " size (1 or not)"); + String ans = + JOptionPane.showInputDialog("Add " + newothermatch + " to entity matches?: (y/n) "); + if (ans != null && "y".equals(ans)) + { // ems.add(newothermatch); + modmatch.addEntityMatch(newothermatch,entities); + ematch.addCondition(guard0); + CorrelationPattern qq = new CorrelationPattern("Conditioned class splitting", + "Class " + realsrc + " split to " + realtrg + ", " + + othere); + qq.addSourceEntity(realsrc); + qq.addTargetEntity(realtrg); + qq.addTargetEntity(othere); + if (res.contains(qq)) { } + else + { res.add(qq); } + } + } + } public EntityMatching isObjectMatch(Vector ems) { Vector spath = new Vector(); @@ -876,18 +1391,16 @@ public EntityMatching isObjectMatch(Vector ems) Type ttrg = trg.getElementType(); // System.out.println(">_>_ " + src + " (" + tsrc + ") " + trg + " (" + ttrg + - // ")"); + // ")"); if (Type.isEntityType(tsrc) && Type.isEntityType(ttrg)) { Entity e1 = tsrc.getEntity(); Entity e2 = ttrg.getEntity(); - EntityMatching emx = ModelMatching.findEntityMatching(e1,ems); - if (emx != null && emx.realtrg != null) - { if (e2.getName().equals(emx.realtrg.getName()) || - Entity.isAncestor(e2,emx.realtrg)) - { return emx; } - } // to map from e1 to e2, emx.realsrc must be e1 or an ancestor of e1, + EntityMatching emx = ModelMatching.findEntityMatchingFor(e1,e2,ems); + if (emx != null) + { return emx; } + // to map from e1 to e2, emx.realsrc must be e1 or an ancestor of e1, // emx.realtrg must be e2 or a descendent of e2 } return null; @@ -941,10 +1454,11 @@ String whenClause(EntityMatching emx, String srcroot, String trgroot, Map whens) return srcentx + "2" + trgentx + "(" + d1 + "," + d2 + ")"; } - String whenClause(String trgroot, Vector ems, Map whens) + String whenClause(String trgroot, String srcobj, Vector ems, Map whens) { // For expr --> trg, need E2F(elementVariable,d2) + if (elementVariable == null) - { return ""; } + { return "true"; } Vector tpath = new Vector(); tpath.addAll(trg.getNavigation()); @@ -954,13 +1468,15 @@ String whenClause(String trgroot, Vector ems, Map whens) Type vtype = elementVariable.getElementType(); if (vtype != null && vtype.isEntity()) { Entity vent = vtype.getEntity(); - // System.out.println(">>> Entity of " + elementVariable + " is " + vent); + // System.out.println(">>> Entity element type of " + elementVariable + " is " + vent); Type ttype = trg.getElementType(); if (ttype != null && ttype.isEntity()) { Entity tent = ttype.getEntity(); - EntityMatching emx = ModelMatching.findEntityMatching(vent,ems); - // System.out.println(">>> Entity match of " + elementVariable + " is " + emx); + EntityMatching emx = ModelMatching.findEntityMatchingFor(vent,tent,ems); + + // System.out.println(">>> Entity match of " + elementVariable + " to " + tent + " is " + emx); + if (emx != null) { String nsrc = emx.src.getName(); String ntrg = emx.trg.getName(); @@ -984,11 +1500,13 @@ String whenClause(String trgroot, Vector ems, Map whens) // be2.variable = trg; // whens.set(be2,be1); + if ("self".equals(elementVariable + "")) + { return srcentx + "2" + trgentx + "(" + srcobj + "," + d2 + ")"; } return srcentx + "2" + trgentx + "(" + elementVariable + "," + d2 + ")"; } } } - return ""; + return "true"; } String sourcedataname(String prefix) @@ -1178,6 +1696,18 @@ String targetequationUMLRSDS(String tvar, Vector bound) return targetequationUMLRSDS(tvar,path,bound); } + String targetequationbx(BasicExpression srcx, BasicExpression trgx, + String prefix,String srcdata,ObjectTemplateExp tExps,Vector whereclause) + { // trgx.nme = srcx.nme and srcx.nme = trgx.nme for non-objects, non-collections + + + Vector path = new Vector(); + path.addAll(trg.getNavigation()); + if (path.size() == 0) + { path.add(trg); } + return targetequationbx(srcx,trgx,prefix,path,srcdata,tExps,whereclause); + } + String targetequation(String prefix, Vector path, String srcdata, ObjectTemplateExp tExp) { // nme = srcdata at the end of the path @@ -1217,7 +1747,12 @@ else if (t.isEntity()) valueExp.setElementType(p.getElementType()); valueExp.variable = src; + + Expression valueExpC = valueExp; + + if (src == null || src.getType() == null) + { System.err.println("!! ERROR: null type in " + src); } if ("String".equals(p.getType() + "") && src.getType().isEnumeration()) { valueExpC = AttributeMatching.dataConversion("QVTR",valueExp, src.getType(), p.getType()); } else if ("String".equals(src.getType() + "") && p.getType().isEnumeration()) @@ -1258,13 +1793,12 @@ else if (path.size() > 1) else { String obj = fullname + "$x"; - Attribute objroot = new Attribute(obj,new Type(tent),ModelElement.INTERNAL); - - if (tent == null) - { System.err.println("!! ERROR: no entity type for " + p); - return ""; - } + if (tent == null) + { System.err.println("!! ERROR: no entity type for " + p); + return ""; + } + Attribute objroot = new Attribute(obj,new Type(tent),ModelElement.INTERNAL); objroot.setElementType(new Type(tent)); ObjectTemplateExp newSubTE = new ObjectTemplateExp(objroot,tent); @@ -1284,7 +1818,10 @@ else if (path.size() > 1) valueExp.variable = src; Expression valueExpC = valueExp; - if ("String".equals(p.getType() + "") && src.getType().isEnumeration()) + + if (src == null || src.getType() == null) + { System.err.println("!! ERROR: null type in " + src); } + else if ("String".equals(p.getType() + "") && src.getType().isEnumeration()) { valueExpC = AttributeMatching.dataConversion("QVTR",valueExp, src.getType(), p.getType()); } else if ("String".equals(src.getType() + "") && p.getType().isEnumeration()) { valueExpC = AttributeMatching.dataConversion("QVTR",valueExp, src.getType(), p.getType()); } @@ -1292,6 +1829,8 @@ else if ("String".equals(src.getType() + "") && p.getType().isEnumeration()) { valueExpC = AttributeMatching.dataConversion("QVTR",valueExp, src.getType(), p.getType()); } else if ("boolean".equals(src.getType() + "") && p.getType().isEnumeration()) { valueExpC = AttributeMatching.dataConversion("QVTR",valueExp, src.getType(), p.getType()); } + else if ("boolean".equals(p.getType() + "") && src.getType().isEnumeration()) + { valueExpC = AttributeMatching.dataConversion("QVTR",valueExp, src.getType(), p.getType()); } tExp.addPTI(p,valueExpC); return pname + " = " + valueExpC; @@ -1299,6 +1838,160 @@ else if ("boolean".equals(src.getType() + "") && p.getType().isEnumeration()) return ""; } // and boolean -> enum data conversions + String targetequationbx(BasicExpression srcx, BasicExpression trgx, + String prefix, Vector path, String srcdata, + ObjectTemplateExp tExp, Vector whereclause) + { // nme = srcdata at the end of the path + + if (path.size() == 1) + { Attribute p = (Attribute) path.get(0); + Type t = p.getType(); + String pname = p.getName(); + String fullname = prefix + "_" + pname; + + if (Type.isCollectionOrEntity(t)) + { Entity tent = null; + Type telem = t.getElementType(); + if (telem != null && telem.isEntity()) + { tent = telem.getEntity(); } + else if (t.isEntity()) + { tent = t.getEntity(); } + + if (tent != null) + { // String defn = pname + " = " + fullname + "$x : " + tent; + // Vector exps = (Vector) tExps.get(defn); + // if (exps == null) + // { exps = new Vector(); } + + // tExps.set(defn,exps); + // return ""; + + String obj = fullname + "$x"; + Attribute objroot = new Attribute(obj,new Type(tent),ModelElement.INTERNAL); + objroot.setElementType(new Type(tent)); + + tExp.addPTI(p,new ObjectTemplateExp(objroot,tent)); + return pname + " = " + fullname + "$x : " + tent + " { }"; + } + } + BasicExpression valueExp = new BasicExpression(src); + valueExp.setObjectRef(srcx); + valueExp.setType(src.getType()); + valueExp.setElementType(src.getElementType()); + valueExp.variable = src; + + BasicExpression tvalueExp = new BasicExpression(trg); + tvalueExp.setObjectRef(trgx); + tvalueExp.setType(trg.getType()); + tvalueExp.setElementType(trg.getElementType()); + tvalueExp.variable = trg; + + + Expression valueExpC = valueExp; + + if (src == null || src.getType() == null) + { System.err.println("!! ERROR: null type in " + src); } + if ("String".equals(p.getType() + "") && src.getType().isEnumeration()) + { valueExpC = AttributeMatching.dataConversion("QVTR",valueExp, src.getType(), p.getType()); } + else if ("String".equals(src.getType() + "") && p.getType().isEnumeration()) + { valueExpC = AttributeMatching.dataConversion("QVTR",valueExp, src.getType(), p.getType()); } + else if (p.getType().isEnumeration() && src.getType().isEnumeration()) + { valueExpC = AttributeMatching.dataConversion("QVTR",valueExp, src.getType(), p.getType()); } + else if (src.getType().isBoolean() && p.getType().isEnumeration()) + { valueExpC = AttributeMatching.dataConversion("QVTR",valueExp, src.getType(), p.getType()); } + else if (p.getType().isBoolean() && src.getType().isEnumeration()) + { valueExpC = AttributeMatching.dataConversion("QVTR",valueExp, src.getType(), p.getType()); } + + Expression tvalueExpC = tvalueExp; + + if (trg == null || trg.getType() == null) + { System.err.println("!! ERROR: null type in " + trg); } + if ("String".equals(p.getType() + "") && src.getType().isEnumeration()) + { tvalueExpC = AttributeMatching.dataConversion("QVTR", tvalueExp, p.getType(), src.getType()); } + else if ("String".equals(src.getType() + "") && p.getType().isEnumeration()) + { tvalueExpC = AttributeMatching.dataConversion("QVTR", tvalueExp, p.getType(), src.getType()); } + else if (p.getType().isEnumeration() && src.getType().isEnumeration()) + { tvalueExpC = AttributeMatching.dataConversion("QVTR", tvalueExp, p.getType(), src.getType()); } + else if (src.getType().isBoolean() && p.getType().isEnumeration()) + { tvalueExpC = AttributeMatching.dataConversion("QVTR", tvalueExp, p.getType(), src.getType()); } + else if (p.getType().isBoolean() && src.getType().isEnumeration()) + { tvalueExpC = AttributeMatching.dataConversion("QVTR", tvalueExp, p.getType(), src.getType()); } + + // tExp.addPTI(p,valueExpC); + + whereclause.add(tvalueExp + " = " + valueExpC + " and " + valueExp + " = " + tvalueExpC); + return tvalueExp + " = " + valueExpC + " and " + valueExp + " = " + tvalueExpC; + } + else if (path.size() > 1) + { Attribute p = (Attribute) path.get(0); + Type t = p.getType(); + String pname = p.getName(); + String fullname = prefix + "_" + pname; + + // (Type.isCollectionOrEntity(t)) + Type telem = t.getElementType(); + Entity tent = telem.getEntity(); + if (tent == null) + { tent = t.getEntity(); } + + Vector pathtail = new Vector(); + pathtail.addAll(path); + pathtail.remove(0); + String body = ""; + // String defn = pname + " = " + fullname + "$x : " + tent; + + Object subtemplate = tExp.getPTI(p); + if (subtemplate instanceof ObjectTemplateExp) + { ObjectTemplateExp subTE = (ObjectTemplateExp) subtemplate; + body = targetequationbx(srcx,trgx,prefix + "_" + pname, pathtail, srcdata, subTE,whereclause); + } + else + { String obj = fullname + "$x"; + + if (tent == null) + { System.err.println("!! ERROR: no entity type for " + p); + return ""; + } + + Attribute objroot = new Attribute(obj,new Type(tent),ModelElement.INTERNAL); + objroot.setElementType(new Type(tent)); + + ObjectTemplateExp newSubTE = new ObjectTemplateExp(objroot,tent); + tExp.addPTI(p,newSubTE); + body = targetequationbx(srcx,trgx,prefix + "_" + pname, pathtail, srcdata, newSubTE,whereclause); + return pname + " = " + obj + " : " + tent + " { " + body + " }"; + } + // return pname + " = " + fullname + "$x : " + tent + " { " + body + " }"; + } + + if (path.size() > 0) + { Attribute p = (Attribute) path.get(0); + String pname = p.getName(); + BasicExpression valueExp = new BasicExpression(srcdata); + valueExp.setType(p.getType()); + valueExp.setElementType(p.getElementType()); + valueExp.variable = src; + + Expression valueExpC = valueExp; + + if (src == null || src.getType() == null) + { System.err.println("!! ERROR: null type in " + src); } + else if ("String".equals(p.getType() + "") && src.getType().isEnumeration()) + { valueExpC = AttributeMatching.dataConversion("QVTR",valueExp, src.getType(), p.getType()); } + else if ("String".equals(src.getType() + "") && p.getType().isEnumeration()) + { valueExpC = AttributeMatching.dataConversion("QVTR",valueExp, src.getType(), p.getType()); } + if (p.getType().isEnumeration() && src.getType().isEnumeration()) + { valueExpC = AttributeMatching.dataConversion("QVTR",valueExp, src.getType(), p.getType()); } + else if ("boolean".equals(src.getType() + "") && p.getType().isEnumeration()) + { valueExpC = AttributeMatching.dataConversion("QVTR",valueExp, src.getType(), p.getType()); } + else if ("boolean".equals(p.getType() + "") && src.getType().isEnumeration()) + { valueExpC = AttributeMatching.dataConversion("QVTR",valueExp, src.getType(), p.getType()); } + + tExp.addPTI(p,valueExpC); + return pname + " = " + valueExpC; + } + return ""; + } // and boolean -> enum data conversions String targetequationUMLRSDS(String tvar, Vector path, Vector bound) { Type ttarg = trg.getType(); @@ -1334,15 +2027,25 @@ String targetequationUMLRSDS(String tvar, Vector path, Vector bound) { Entity sentity = selem.getEntity(); String sename = sentity.getName(); String sId = sename.toLowerCase() + "Id"; + + Attribute srcpk = sentity.getPrincipalPK(); + if (srcpk != null) + { sId = srcpk + ""; } + String srclookup = tename + "[" + src + "." + sId + "]"; // src is a feature + if (multsrc != ModelElement.ONE && multtrg == ModelElement.ONE) - { res = tvar + "." + trg + " = " + srclookup + "->any()"; } + { srclookup = tename + "[" + src + "->collect(" + sId + ")]"; + res = tvar + "." + trg + " = " + srclookup + "->any()"; + } else if (multsrc == ModelElement.ONE && multtrg != ModelElement.ONE) { res = srclookup + " : " + tvar + "." + trg; } - else if ("Sequence".equals(t.getName()) && "Set".equals(src.getType().getName())) + else if (src.getType() != null && + "Sequence".equals(t.getName()) && "Set".equals(src.getType().getName())) { res = tvar + "." + trg + " = " + srclookup + "->asSequence()"; } - else if ("Set".equals(t.getName()) && "Sequence".equals(src.getType().getName())) + else if (src.getType() != null && + "Set".equals(t.getName()) && "Sequence".equals(src.getType().getName())) { res = tvar + "." + trg + " = " + srclookup + "->asSet()"; } else { res = tvar + "." + trg + " = " + srclookup; } @@ -1369,10 +2072,17 @@ else if (t != null && t.isEntity()) String sename = sentity.getName(); String sId = sename.toLowerCase() + "Id"; - String srclookup = tename + "[" + src + "." + sId + "]"; // src is a feature + Attribute srcpk = sentity.getPrincipalPK(); + if (srcpk != null) + { sId = srcpk + ""; } + + String srclookup = tename + "[" + src + "." + sId + "]"; // src is a feature + if (multsrc != ModelElement.ONE && multtrg == ModelElement.ONE) - { res = tvar + "." + trg + " = " + srclookup + "->any()"; } + { srclookup = tename + "[" + src + "->collect(" + sId + ")]";; + res = tvar + "." + trg + " = " + srclookup + "->any()"; + } else if (multsrc == ModelElement.ONE && multtrg != ModelElement.ONE) { res = srclookup + " : " + tvar + "." + trg; } else @@ -1393,6 +2103,7 @@ else if (multsrc == ModelElement.ONE && multtrg != ModelElement.ONE) return res; } + // For UML-RSDS: String composedTargetEquation(String tvar, Vector created) { Vector path = new Vector(); path.addAll(trg.getNavigation()); @@ -1415,11 +2126,19 @@ String composedTargetEquation(String tvar, Vector created) prex = preatt.getName(); // ModelElement.composeNames(preatt); tvar1 = tvar + "." + prex; pathrem.addAll(path); - pathrem.removeAll(preattp); + // System.out.println("PATH=" + pathrem + " " + preattp); + // pathrem.removeAll(preattp); + // System.out.println("PATHREM=" + pathrem); + for (int xx = 0; xx < preattp.size(); xx++) + { String xxs = ((Attribute) preattp.get(xx)).getName(); + pathrem = VectorUtil.removeByName(pathrem,xxs); + } // Does this make sense? + Type tpreatt = preatt.getElementType(); if (tpreatt != null && tpreatt.isEntity()) { preattD = tpreatt.getEntity(); } // System.out.println(">>> Already created " + preatt + " : " + preattD + " followed by " + pathrem); + alreadycreated = true; multiple = preatt.isManyValued(); } @@ -1441,18 +2160,22 @@ else if (Type.isEntityCollection(t)) // String shortename = ename.substring(0,ename.length()-1); // target feature element type Type stype = src.getElementType(); + Attribute bpk = null; if (Type.isEntityType(stype)) { b = stype.getEntity(); bname = b.getName(); // sname = bname.substring(0,bname.length()-1); // source feature element type + bpk = b.getPrincipalPK(); } String bId = bname.toLowerCase() + "Id"; + if (bpk != null) + { bId = bpk.getName(); } String evar = ename.toLowerCase() + "$x"; String evardec = ""; if (Type.isCollectionType(src.getType()) && b != null) - { evardec = " & " + evar + " : " + ename + "[" + src + "." + bId + "] => \n"; } + { evardec = " & " + evar + " : " + ename + "[" + src + "->collect(" + bId + ")] => \n"; } else if (b != null) { evardec = " & " + evar + " = " + ename + "[" + src + "." + bId + "] => \n"; } else if (Type.isCollectionType(src.getType())) @@ -1461,7 +2184,11 @@ else if (Type.isCollectionType(src.getType())) { evardec = " & " + evar + " = " + src + " => \n"; } if (alreadycreated) - { if (multiple) + { // System.out.println("* source: " + srcexp.isMultipleValued() + " * " + preatt + " " + + // multiple + " * " + pathrem + " " + + // Attribute.isMultipleValued(pathrem)); + + if (multiple) { if (srcexp.isMultipleValued() && !Attribute.isMultipleValued(pathrem)) { // ignore the existing elements in tvar1 and create new ones for the new srcexp. @@ -1523,7 +2250,11 @@ else if (Type.isCollectionType(src.getType())) else { String evar = src + ""; if (alreadycreated) - { if (multiple) + { // System.out.println("Valuetype * source: " + srcexp.isMultipleValued() + " * " + preatt + " " + + // multiple + " * " + pathrem + " " + + // Attribute.isMultipleValued(pathrem)); + + if (multiple) { String cteq0 = composedTargetEquation(srcexp,"_y",evar,pathrem); if (cteq0.length() > 0) { return " =>\n" + @@ -1571,7 +2302,11 @@ String composedTargetEquationExpr(Expression srcexp, String tvar, Vector created prex = preatt.getName(); // ModelElement.composeNames(preatt); tvar1 = tvar + "." + prex; pathrem.addAll(path); - pathrem.removeAll(preattp); + // pathrem.removeAll(preattp); + for (int xx = 0; xx < preattp.size(); xx++) + { String xxs = ((Attribute) preattp.get(xx)).getName(); + pathrem = VectorUtil.removeByName(pathrem,xxs); + } // System.out.println(">>> Already created " + preatt + " " + tvar1 + " " + pathrem); alreadycreated = true; multiple = preatt.isManyValued(); @@ -1597,12 +2332,17 @@ else if (Type.isEntityCollection(t)) Entity b = null; Type stype = srcexp.getElementType(); + Attribute bpk = null; + if (Type.isEntityType(stype)) { b = stype.getEntity(); bname = b.getName(); // source expression element type + bpk = b.getPrincipalPK(); } String bId = bname.toLowerCase() + "Id"; + if (bpk != null) + { bId = bpk.getName(); } String evar = ename.toLowerCase() + "$x"; String evardec = ""; @@ -1705,7 +2445,10 @@ else if (Type.isCollectionType(srctype)) } public String composedTargetEquation(Expression srcexp, String tvar, String evar, Vector path) - { if (path.size() == 1) + { // System.out.println("CTEq: source: " + srcexp + " tvar " + tvar + " evar " + + // evar + " path: " + path); + + if (path.size() == 1) { Attribute p = (Attribute) path.get(0); Type t = p.getType(); Type tsrc = srcexp.getType(); @@ -1742,6 +2485,11 @@ else if (tsrc.isBoolean() && t.isEnumeration()) Expression texp = AttributeMatching.dataConversion("UML-RSDS",sexp,tsrc,t); return tvar + "." + p.getName() + " = " + texp; } + else if (t.isBoolean() && tsrc.isEnumeration()) + { BasicExpression sexp = new BasicExpression(evar); + Expression texp = AttributeMatching.dataConversion("UML-RSDS",sexp,tsrc,t); + return tvar + "." + p.getName() + " = " + texp; + } else { return tvar + "." + p.getName() + " = " + evar; } } @@ -1788,7 +2536,11 @@ String targetequationQVTO(Expression tvar, Expression srcdata, Vector ems, Vecto String tvar1 = tvar + "." + prex; Vector pathrem = new Vector(); pathrem.addAll(path); - pathrem.removeAll(preattp); + for (int xx = 0; xx < preattp.size(); xx++) + { String xxs = ((Attribute) preattp.get(xx)).getName(); + pathrem = VectorUtil.removeByName(pathrem,xxs); + } + // pathrem.removeAll(preattp); // System.out.println(">>> Already created " + preatt + " " + tvar1 + " " + pathrem); if (preatt.isManyValued()) { if (srcdata.isMultipleValued() && @@ -1852,7 +2604,7 @@ else if (tent != null) if (selem != null && selem.isEntity()) { s = selem.getEntity(); } - EntityMatching em = ModelMatching.findEntityMatching(s,ems); + EntityMatching em = ModelMatching.findEntityMatchingFor(s,tent,ems); // System.out.println("Entity matching for " + s + " is " + em); if (em != null && smult == ModelElement.ONE) @@ -1883,7 +2635,7 @@ else if (tent != null) if (selem != null && selem.isEntity()) { s = selem.getEntity(); } - EntityMatching em = ModelMatching.findEntityMatching(s,ems); + EntityMatching em = ModelMatching.findEntityMatchingFor(s,tent,ems); // System.out.println("Entity matching for " + s + " is " + em); if (em != null && smult == ModelElement.ONE) @@ -1939,6 +2691,13 @@ else if (path.size() > 1) // created.add(trg.getNavigation()); } // tvar + "." + trg + " := " + svar + "." + src + ";"; } + + if (src.getUpper() == 1 && src.getLower() == 0) + { String testnull = "if (" + svar + " = null) then {} else { " + + res + " } endif"; + return testnull; + } + return res; } @@ -1958,6 +2717,12 @@ private String qvtoObjectFor(Attribute previous, Vector path, if (path.size() == 1) { Attribute p = (Attribute) path.get(0); Entity t = p.getOwner(); + if (t != null && t.isConcrete()) { } + else + { System.err.println("!! Cannot instanciate owner " + t + " of " + p); + t = previous.getElementType().getEntity(); + } + String pname = p.getName(); Type ptype = p.getType(); @@ -1981,14 +2746,14 @@ private String qvtoObjectFor(Attribute previous, Vector path, if (previous != null && previous.isManyValued() && src.isManyValued()) { String xresolve = "_x.resolveone()"; - if (selem.isEntity()) - { EntityMatching emx = ModelMatching.findEntityMatching(selem.getEntity(), ems); - String desttype = ""; + if (selem.isEntity() && pent != null) + { EntityMatching emx = ModelMatching.findEntityMatchingFor(selem.getEntity(), pent, ems); + String desttype = pent.getName(); if (emx != null) - { if (pent != null) - { desttype = pent.getName(); } - else - { desttype = emx.realtrg.getName(); } + { // if (pent != null) + // { desttype = pent.getName(); } + // else + // { desttype = emx.realtrg.getName(); } xresolve = "_x.resolveoneIn(" + emx.realsrc + "::" + emx.realsrc + "2" + emx.realtrg + ", " + desttype + ")"; @@ -2015,13 +2780,20 @@ else if (ptype.getName().equals("Set")) { if (pent != null && selem != null && selem.isEntity()) { Entity s = selem.getEntity(); - EntityMatching em = ModelMatching.findEntityMatching(s,ems); + EntityMatching em = ModelMatching.findEntityMatchingFor(s,pent,ems); // System.out.println("Entity matching for " + s + " is " + em); - String res = pname + " " + pop + " " + svar + "." + + if (em != null) + { String res = pname + " " + pop + " " + svar + "." + "resolveoneIn(" + em.realsrc + "::" + em.realsrc + "2" + em.realtrg + ", " + pent.getName() + ");"; - result = tvar + " " + operator + " object " + t + " { " + res + " };"; + result = tvar + " " + operator + " object " + t + " { " + res + " };"; + } + else + { System.err.println(">>> no entity matching for " + s + " Incomplete mapping."); + String res = pname + " " + pop + " " + svar + "." + "resolveone();"; + result = tvar + " " + operator + " object " + t + " { " + res + " };"; + } } else { result = tvar + " " + operator + " object " + t + @@ -2036,6 +2808,12 @@ else if (path.size() > 1) Vector pathtail = new Vector(); pathtail.addAll(path); pathtail.remove(0); + + if (t != null && t.isConcrete()) { } + else + { System.err.println("!! Cannot create instance of owner " + t + " of " + p); + t = previous.getElementType().getEntity(); + } BasicExpression xexp = new BasicExpression("_x"); xexp.setType(svar.getElementType()); @@ -2055,9 +2833,9 @@ else if (path.size() > 1) - String atldirecttarget(String svar) + String atldirecttarget(String svar, Vector ems) { Expression sexp = // new BasicExpression(svar + "." + src); - src.atlComposedExpression(svar); + src.atlComposedExpression(svar,trg,ems); Expression vexp = sexp; Type stype = src.getType(); Type ttype = trg.getType(); @@ -2085,6 +2863,36 @@ else if (stype != null && ttype != null && return trg + " <- " + vexp; } + Binding atldirectbinding(String svar, Vector ems) + { Expression sexp = // new BasicExpression(svar + "." + src); + src.atlComposedExpression(svar,trg,ems); + Expression vexp = sexp; + Type stype = src.getType(); + Type ttype = trg.getType(); + if (stype != null && ttype != null && + "String".equals(ttype.getName()) && stype.isEnumeration()) + { vexp = AttributeMatching.dataConversion("ATL", sexp, stype, ttype); } + else if (stype != null && ttype != null && + "String".equals(stype.getName()) && ttype.isEnumeration()) + { vexp = AttributeMatching.dataConversion("ATL", sexp, stype, ttype); } + // or both are enums, or one boolean and the other enum + else if (stype != null && ttype != null && + stype.isEnumeration() && ttype.isEnumeration()) + { vexp = AttributeMatching.dataConversion("ATL", sexp, stype, ttype); } + else if (stype != null && ttype != null && + "boolean".equals(ttype.getName()) && stype.isEnumeration()) + { vexp = new BasicExpression("thisModule." + stype.getName() + "2boolean" + trg.getName() + + "(" + sexp + ")"); } + else if (stype != null && ttype != null && + "boolean".equals(stype.getName()) && ttype.isEnumeration()) + { vexp = new BasicExpression("thisModule.boolean2" + ttype.getName() + src.getName() + + "(" + sexp + ")"); + } + + Binding bres = new Binding(trg + "", vexp); + return bres; + } + Binding atlcomposedtarget(Vector newclauses, Vector newrules, Vector newdo, String srcvar, String trgvar, Entity realsrc, Vector created, java.util.Map implementedBy) @@ -2113,8 +2921,11 @@ Binding atlcomposedtarget(Vector newclauses, Vector newrules, Vector newdo, BasicExpression srcexvar = new BasicExpression(srcvar); Expression expr; - if (isExpressionAssignment()) - { expr = srcvalue.addReference(srcexvar, new Type(realsrc)); } + if (srcvalue != null) + { expr = srcvalue.addReference(srcexvar, new Type(realsrc)); + expr.setType(srcvalue.getType()); + expr.setElementType(srcvalue.getElementType()); + } else { expr = new BasicExpression(src); ((BasicExpression) expr).setObjectRef(srcexvar); @@ -2122,7 +2933,7 @@ Binding atlcomposedtarget(Vector newclauses, Vector newrules, Vector newdo, if (preset != null && (preset instanceof Attribute)) - { // System.out.println(">>> Additional mapping " + expr + " �-> " + trg); + { // System.out.println(">>> Additional mapping " + expr + " ?-> " + trg); Attribute trgref = trg.objectReference(); Attribute f = trg.getFinalFeature(); @@ -2201,6 +3012,9 @@ Binding atlTargetMap(Attribute preatt, Vector path, Expression sexpr, dx = p1x + "_" + d.getName().toLowerCase() + "_x"; dxvar = new Attribute(dx, new Type(d), ModelElement.INTERNAL); dxvar.setElementType(new Type(d)); + if (d != null && d.isConcrete()) { } + else + { System.err.println("!! Cannot instantiate entity " + d); } } Entity srcent = null; @@ -2473,5 +3287,657 @@ else if (p1.isSingleValued()) } } + Statement etldirecttarget(String svar, BasicExpression directtarget, Vector ems) + { Expression sexp = // new BasicExpression(svar + "." + src); + src.etlComposedExpression(svar,trg,ems); + Expression vexp = sexp; + Type stype = src.getType(); + Type ttype = trg.getType(); + if (stype != null && ttype != null && + "String".equals(ttype.getName()) && stype.isEnumeration()) + { vexp = new BasicExpression("(" + sexp + ")." + stype.getName() + "2String()"); } + else if (stype != null && ttype != null && + "String".equals(stype.getName()) && ttype.isEnumeration()) + { vexp = new BasicExpression("(" + sexp + ").String2" + ttype.getName() + "()"); } + else if (stype != null && ttype != null && + stype.isEnumeration() && ttype.isEnumeration()) + { vexp = new BasicExpression("(" + sexp + ").convert" + stype.getName() + "_" + + ttype.getName() + "()"); + } + else if (stype != null && ttype != null && + "boolean".equals(ttype.getName()) && stype.isEnumeration()) + { vexp = new BasicExpression("(" + sexp + ")." + stype.getName() + "2boolean" + trg.getName() + + "()"); } + else if (stype != null && ttype != null && + "boolean".equals(stype.getName()) && ttype.isEnumeration()) + { vexp = new BasicExpression("(" + sexp + ").boolean2" + + ttype.getName() + src.getName() + "()"); + } + + AssignStatement res = new AssignStatement(directtarget, vexp); + if (src.getUpper() == 1 && src.getLower() == 0) + { BasicExpression testnull = new BasicExpression("isDefined"); + testnull.setParameters(new Vector()); + testnull.setObjectRef(new BasicExpression(svar + "." + src)); + return new ConditionalStatement(testnull, res); + } + return res; + } + + Statement etlcomposedtarget(Vector newclauses, Vector newrules, Vector statements, + String srcvar, String trgvar, Entity realsrc, + Vector created, java.util.Map implementedBy, Vector ems) + { Vector path = trg.getNavigation(); + if (path.size() == 0) + { path.add(trg); } + + Attribute preatt = null; + Vector preattp = VectorUtil.largestInitialSegment(path,created); + Object preset = null; + + if (preattp != null && preattp.size() > 0) + { preatt = new Attribute(preattp); + String prex = preatt.getName(); // ModelElement.composeNames(preatt); + // String tvar1 = tvar + "." + prex; + Vector pathrem = new Vector(); + pathrem.addAll(path); + pathrem.removeAll(preattp); + preset = implementedBy.get(prex); + // System.out.println(">>> Already created " + preattp + " " + prex + " " + pathrem); + // System.out.println(">>> Implemented by " + preset); + } + // else if (path.size() > 0) + // { preatt = (Attribute) path.get(0); } + + BasicExpression srcexvar = new BasicExpression(srcvar); + Expression expr; + + if (srcvalue != null) + { expr = srcvalue.addReference(srcexvar, new Type(realsrc)); + expr.setType(srcvalue.getType()); + expr.setElementType(srcvalue.getElementType()); + } + else + { expr = new BasicExpression(src); + ((BasicExpression) expr).setObjectRef(srcexvar); + } + + + if (preset != null && (preset instanceof Attribute)) + { // System.out.println(">>> Additional mapping " + expr + " ?-> " + trg); + Attribute trgref = trg.objectReference(); + Attribute f = trg.getFinalFeature(); + + if (trgref.isMultiValued()) + { // System.out.println(f + " upper bound is " + f.upperBound()); + // System.out.println(expr + " upper bound is " + expr.upperBound()); + + if (f.upperBound() >= expr.upperBound()) + { // convert expr by using equivalent. + Expression xf = new BasicExpression("_x." + f); + Expression expretl = expr.etlEquivalent(trg,ems); + AssignStatement body = new AssignStatement(xf, expretl); + Expression test = new BasicExpression("_x in " + trgvar + "." + trgref); + WhileStatement ws = new WhileStatement(test,body); + ws.setLoopKind(Statement.FOR); + statements.add(ws); + } + else + { Binding res = etlTargetMap(trgvar,preatt,path,expr,newclauses,newrules,implementedBy,ems); + if (res == null) + { return null; } + + AssignStatement astat = new AssignStatement(res); + + if (src.getUpper() == 1 && src.getLower() == 0) + { BasicExpression testnull = new BasicExpression("isDefined"); + testnull.setParameters(new Vector()); + testnull.setObjectRef(expr); + return new ConditionalStatement(testnull, astat); + } + return astat; + } + } + else if (f.upperBound() >= expr.upperBound()) + { Expression expretl = expr.etlEquivalent(trg,ems); + AssignStatement as1 = new AssignStatement(trgvar + "." + trg, expretl); + if (src.getUpper() == 1 && src.getLower() == 0) + { BasicExpression testnull = new BasicExpression("isDefined"); + testnull.setParameters(new Vector()); + testnull.setObjectRef(expr); + statements.add(new ConditionalStatement(testnull, as1)); + } + statements.add(as1); + } + else + { Expression expretl = expr.etlEquivalent(trg,ems); + AssignStatement as2 = new AssignStatement(trgvar + "." + trg, + new UnaryExpression("->any", expretl)); + statements.add(as2); + } + + return null; + } + else + { Binding res = etlTargetMap(trgvar,preatt,path,expr,newclauses,newrules,implementedBy,ems); + if (res == null) { return null; } + AssignStatement ast2 = new AssignStatement(res); + if (src.getUpper() == 1 && src.getLower() == 0) + { BasicExpression testnull = new BasicExpression("isDefined"); + testnull.setParameters(new Vector()); + testnull.setObjectRef(expr); + return new ConditionalStatement(testnull, ast2); + } + return ast2; + + } + } + +Binding etlTargetMap(String trgvar, Attribute preatt, Vector path, Expression sexpr, + Vector newclauses, Vector newrules, java.util.Map implementedBy, + Vector ems) +{ if (path.size() == 0) + { return null; } + Attribute p1 = (Attribute) path.get(0); + String p1x = p1.getName(); + + String preattname = ""; + if (preatt != null) + { preattname = preatt.getName(); } + else + { preatt = p1; + preattname = p1x; + } + + Vector pathtail = new Vector(); + pathtail.addAll(path); + pathtail.remove(0); + Type p1type = p1.getElementType(); + Entity d = null; + String dx = ""; + Attribute dxvar = null; + + Attribute nextatt = null; + if (preatt != null) + { Vector prepath = preatt.getNavigation(); + Vector route = new Vector(); + route.addAll(prepath); + route.add(p1); + nextatt = new Attribute(route); + } + + if (p1type == null) + { // Expression expretl = sexpr.etlEquivalent(trg,ems); + Binding bres = new Binding(trgvar + "." + p1x, sexpr); + return bres; + // return trgvar + "." + p1x + " := " + sexpr; + } + + + if (p1type.isEntity()) + { d = p1type.getEntity(); + dx = p1x + "_" + d.getName().toLowerCase() + "_x"; + dxvar = new Attribute(dx, new Type(d), ModelElement.INTERNAL); + dxvar.setElementType(new Type(d)); + if (d != null && d.isConcrete()) { } + else + { System.err.println("!!! Cannot instantiate " + d); } + } + + Entity srcent = null; + String sx = ""; + Attribute srcvar = null; + + Type srctype = sexpr.getElementType(); + + if (Type.isEntityType(srctype)) + { srcent = srctype.getEntity(); + sx = srcent.getName().toLowerCase() + "_x"; + srcvar = new Attribute(sx,new Type(srcent),ModelElement.INTERNAL); + srcvar.setElementType(new Type(srcent)); + } + else if (srctype != null) // eg, for String + { // sx = srctype.getName().toLowerCase() + "$x"; + sx = Identifier.nextIdentifier("var_"); + srcvar = new Attribute(sx,srctype,ModelElement.INTERNAL); + srcvar.setElementType(srctype); + } + else // for int, long, boolean, etc + { // System.err.println("!! Null element type in " + sexpr); + srctype = sexpr.getType(); + if (srctype == null) + { Binding bres1 = new Binding(trgvar + "." + p1x,sexpr); + return bres1; + // Do conversions using equivalent. + } + sx = Identifier.nextIdentifier("var_"); + // srctype.getName().toLowerCase() + "$x"; + srcvar = new Attribute(sx,srctype,ModelElement.INTERNAL); + srcvar.setElementType(srctype); + } + + if (path.size() > 1) + { if (p1.isSingleValued()) + { Binding sexp = etlTargetMap(dx,nextatt,pathtail,sexpr, + newclauses,newrules,implementedBy,ems); + // String newclause = " " + dx + " : " + d.getName() + "\n" + + // " ( " + sexp + " )"; + // newclauses.add(newclause); + Binding bres2 = new Binding(trgvar + "." + p1x, new BasicExpression(dxvar)); + + OutPatternElement ope = null; + if (implementedBy.get(preattname) != null && + implementedBy.get(preattname) instanceof OutPatternElement) + { ope = (OutPatternElement) implementedBy.get(preattname); + ope.addBinding(sexp); + // implementedBy.put(preattname, ope); + return null; + } + else + { ope = new OutPatternElement(dxvar); + if (src.getLower() == 0 && src.getUpper() == 1) + { BasicExpression isdefined = new BasicExpression("isDefined"); + isdefined.setParameters(new Vector()); + isdefined.setObjectRef(sexpr); + ope.setCondition(isdefined); + } + newclauses.add(ope); + ope.addBinding(sexp); + implementedBy.put(preattname, ope); + return bres2; + } + } + else // p1 not ONE + { if (sexpr.isMultipleValued() && srcent != null) + { Binding sexp2 = etlTargetMap(dx,nextatt,pathtail,new BasicExpression(srcvar), + newclauses,newrules,implementedBy,ems); + String newmap = "Map" + srcent + "2" + d + "_" + ModelElement.underscoredNames(pathtail); + // String newrule = " unique lazy rule " + newmap +"\n" + + // " { from " + sx + " : MM1!" + srcent + "\n" + + // " to " + dx + " : MM2!" + d + "\n" + + // " ( " + sexp2 + " )\n" + + // " }"; + // newrules.add(newrule); + + TransformationRule mr = new TransformationRule(newmap,true,false); + mr.setSource(srcvar); + // OutPattern op = new OutPattern(); + OutPatternElement ope = new OutPatternElement(dxvar); + ope.addBinding(sexp2); + // implementedBy.put(preattname, ope); + implementedBy.put(preattname, preatt); + // op.setElement(ope); + mr.addClause(ope); + if (newrules.contains(mr)) { } + else + { newrules.add(mr); } + + + BinaryExpression crange = new BinaryExpression(":",new BasicExpression(sx),sexpr); + BasicExpression mapcall = new BasicExpression(sx + ".equivalent('" + newmap + "')"); + BinaryExpression collexp = new BinaryExpression("|C", crange, mapcall); + Binding bres3 = new Binding(trgvar + "." + p1x, collexp); + + return bres3; + // return p1x + " <- " + + // sexpr + "->collect( " + sx + " | thisModule." + newmap + "(" + sx + "))"; + } + else if (sexpr.isMultipleValued()) + { Binding sexp2 = etlTargetMap(dx,nextatt,pathtail,new BasicExpression(srcvar), + newclauses,newrules,implementedBy,ems); + String newmap = "Map" + srctype + "2" + d + "_" + ModelElement.underscoredNames(pathtail); + // String newrule = " rule " + newmap +"(" + sx + " : " + srctype + ")\n" + + // " { to " + dx + " : " + d + "\n" + + // " ( " + sexp2 + " )\n" + + // " }"; + // newrules.add(newrule); + + // OutPatternElement ope = null; + // MatchedRule mr = new MatchedRule(false,false); + Type rettype = new Type(d); + BehaviouralFeature bf = new BehaviouralFeature(newmap,new Vector(),false,rettype); + Vector stats = new Vector(); + CreationStatement decvar = new CreationStatement(d + "", dx); + decvar.setInitialValue("new MM2!" + d); + stats.add(decvar); + Binding sexp3 = sexp2.substitute(sx,new BasicExpression("self")); + stats.add(new AssignStatement(sexp3)); + + stats.add(new ReturnStatement(new BasicExpression(dx))); + bf.setActivity(new SequenceStatement(stats)); + + if (srcent != null) + { bf.setOwner(srcent); } + else + { bf.setOwner(new Entity(srctype + "")); } + // mr.addParameter(srcvar); + // OutPattern op = new OutPattern(); + // ope = new OutPatternElement(dxvar); + // op.setElement(ope); + // mr.setOutPattern(op); + + if (newrules.contains(bf)) { } + else + { newrules.add(bf); } + + // ope.addBinding(sexp2); + implementedBy.put(preattname,preatt); + // An operation in ETL + + BinaryExpression crange = new BinaryExpression(":",new BasicExpression(sx),sexpr); + BasicExpression mapcall = new BasicExpression(sx + "." + newmap + "()"); + BinaryExpression collexp = new BinaryExpression("|C", crange, mapcall); + Binding bres4 = new Binding(trgvar + "." + p1x,collexp); + return bres4; + // return p1x + " <- " + + // sexpr + "->collect( " + sx + " | thisModule." + newmap + "(" + sx + "))"; + } + else // if (srcent != null) // sexpr single-valued, object + { // Binding sexp2 = atlTargetMap(nextatt,pathtail,new BasicExpression(srcvar), + // newclauses,newrules,implementedBy); + // String newmap = "Map" + srcent + "2" + d; + Binding sexp = etlTargetMap(dx,nextatt,pathtail,sexpr,newclauses, + newrules,implementedBy,ems); + // String newclause = " " + dx + " : " + d.getName() + "\n" + + // " ( " + sexp + " )"; + // newclauses.add(newclause); + Binding bres2 = new Binding(trgvar + "." + p1x, new BasicExpression(dxvar)); + // String newrule = " unique lazy rule " + newmap +"\n" + + // " { from " + sx + " : MM1!" + srcent + "\n" + + // " to " + dx + " : MM2!" + d + "\n" + + // " ( " + sexp2 + " )\n" + + // " }"; + // newrules.add(newrule); + + OutPatternElement ope = null; + if (implementedBy.get(preattname) != null && + implementedBy.get(preattname) instanceof OutPatternElement) + { ope = (OutPatternElement) implementedBy.get(preattname); + ope.addBinding(sexp); + // implementedBy.put(preattname,ope); + return null; + } + else + { ope = new OutPatternElement(dxvar); + // MatchedRule mr = new MatchedRule(true,true); + // mr.setName(newmap); + // InPattern ip = new InPattern(); + // InPatternElement ipe = new InPatternElement(srcvar,null); + // ip.addElement(ipe); + // OutPattern op = new OutPattern(); + // ope = new OutPatternElement(dxvar); + // op.setElement(ope); + // mr.setInPattern(ip); + // mr.setOutPattern(op); + // newrules.add(mr); + ope.addBinding(sexp); + newclauses.add(ope); + implementedBy.put(preattname,ope); + return bres2; + } + } + } + } + else // path.size() == 1 + { if (p1.isSingleValued() && sexpr.isSingleValued()) + { Expression expretl = sexpr.etlEquivalent(p1,ems); + Binding res7 = new Binding(trgvar + "." + p1x, expretl); + return res7; + } + else if (p1.isSingleValued()) + { Expression expretl = sexpr.etlEquivalent(p1,ems); + UnaryExpression anyexp = new UnaryExpression("->any", expretl); + Binding bres8 = new Binding(trgvar + "." + p1x, anyexp); + return bres8; + // return p1x + " <- (" + sexpr + ")->any()"; + } + else + { Expression expretl = sexpr.etlEquivalent(p1,ems); + Binding res9 = new Binding(trgvar + "." + p1x, expretl); + return res9; + // return p1x + " <- " + sexpr; + } + } +} + + + public void checkModel(ModelSpecification mod, + Vector srcobjs, Vector trgobjs) + { // For each feature mapping f |--> g, checks for each + // ex : E and corresponding fx : F, that ex.f = fx.g in + // the model. + + Type selemt = src.getElementType(); + Type telemt = trg.getElementType(); + String sent = ""; + String tent = ""; + if (selemt != null && selemt.isEntityType()) + { sent = selemt.getEntity().getName(); } + if (telemt != null && telemt.isEntityType()) + { tent = telemt.getEntity().getName(); } + + boolean valid = true; + double[] xs = new double[srcobjs.size()]; + double[] ys = new double[trgobjs.size()]; + Vector xlist = new Vector(); + java.util.Map ymap = new java.util.HashMap(); + + String[] xstrs = new String[srcobjs.size()]; + String[] ystrs = new String[trgobjs.size()]; + + Vector[] xvect = new Vector[srcobjs.size()]; + Vector[] yvect = new Vector[trgobjs.size()]; + + for (int i = 0; i < srcobjs.size() && i < trgobjs.size(); i++) + { ObjectSpecification sobj = (ObjectSpecification) srcobjs.get(i); + ObjectSpecification tobj = (ObjectSpecification) trgobjs.get(i); + if (src.isNumeric() && trg.isNumeric()) + { double srcval = sobj.getNumeric(src.getName()); + xs[i] = srcval; + Double xv = new Double(srcval); + xlist.add(xv); + double trgval = tobj.getNumeric(trg.getName()); + ys[i] = trgval; + ymap.put(xv,new Double(trgval)); + + if (srcval == trgval) + { System.out.println(">> objects " + sobj + " " + tobj + " satisfy matching " + this); } + else + { System.out.println("!! objects " + sobj + " " + tobj + " fail to satisfy matching " + this); + valid = false; + } + System.out.println("----------------------"); + } + else if (src.isString() && trg.isString()) + { String srcstr = sobj.getString(src.getName()); + String trgstr = tobj.getString(trg.getName()); + xstrs[i] = srcstr; + ystrs[i] = trgstr; + + if (srcstr.equals(trgstr)) + { System.out.println(">> objects " + sobj + " " + tobj + " satisfy matching " + this); } + else + { System.out.println("!! objects " + sobj + " " + tobj + " fail to satisfy matching " + this); + valid = false; + } + System.out.println("----------------------"); + } + else if (src.isCollection() && trg.isCollection()) + { Vector srcvect = sobj.getCollection(src.getName()); + Vector trgvect = tobj.getCollection(trg.getName()); + + xvect[i] = srcvect; + yvect[i] = trgvect; + + if (src.isSequence() && trg.isSequence()) + { if (srcvect.equals(trgvect)) + { System.out.println(">> objects " + sobj + " " + tobj + " satisfy matching " + this); } + else if (mod.correspondingObjectSequences(sent,tent,srcvect,trgvect)) + { System.out.println(">> objects " + sobj + " " + tobj + " satisfy matching " + this); } + else + { System.out.println("!! objects " + sobj + " " + tobj + " fail to satisfy matching " + this); + valid = false; + } + } + else if (src.isSet() && trg.isSet()) + { System.out.println(srcvect + " " + trgvect); + if (srcvect.containsAll(trgvect) && trgvect.containsAll(srcvect)) + { System.out.println(">> objects " + sobj + " " + tobj + " satisfy matching " + this); } + else if (mod.correspondingObjectSets(sent,tent,srcvect,trgvect)) + { System.out.println(">> objects " + sobj + " " + tobj + " satisfy matching " + this); } + else + { System.out.println("!! objects " + sobj + " " + tobj + " fail to satisfy matching " + this); + valid = false; + } + } + System.out.println("----------------------"); + } + } + + if (!valid && src.isNumeric() && trg.isNumeric()) + { // check if the x and y are constant, or + // linearly or quadratically correlated. + // If so, derive the x to y function + + if (AuxMath.isFunctional(xs,ys)) { } + else + { System.out.println(">>> " + trg + " is not a function of " + src); + return; + } + + if (AuxMath.isConstant(ys)) + { System.out.println(">>> " + trg + " is constant."); + System.out.println(ys[0] + " |--> " + trg); + System.out.println(); + } + else + { double corr = AuxMath.linearCorrelation(xs,ys); + if (corr > 0.95) + { System.out.println(">>> The " + src + " and " + trg + + " values are linearly related with correlation " + corr); + double slope = AuxMath.linearSlope(); + double offset = AuxMath.linearOffset(); + System.out.println(slope + "*" + src + " + " + offset + " |--> " + trg); + System.out.println(); + } + else + { // sort the ys by increasing xs + List sortedxs = new Vector(); + sortedxs.addAll(xlist); + Collections.sort(sortedxs); + System.out.println(sortedxs); + List ylist = new Vector(); + for (int g = 0; g < sortedxs.size(); g++) + { ylist.add(ymap.get(sortedxs.get(g))); } + System.out.println(ylist); + + double[] ys2 = new double[ylist.size()]; + for (int k = 0; k < ylist.size(); k++) + { ys2[k] = + ((Double) ylist.get(k)).doubleValue(); + } + + AuxMath.slopes(ys2); + boolean quad = AuxMath.quadraticRelationship(xs,ys2, + src.getName(),trg.getName()); + System.out.println(">>> Quadratic " + quad); + + if (!quad) + { double isexp = AuxMath.isExponential(xs,ys2); + System.out.println(">>> Exponential: " + isexp); + if (isexp > 0.9) + { AuxMath.exponentialRelationship(src.getName(),trg.getName()); } + } + } + } + } + + if (!valid && src.isString() && trg.isString()) + { // System.out.println(xstrs[0]); + // System.out.println(ystrs[0]); + if (AuxMath.isConstant(ystrs)) + { System.out.println(">>> " + trg + " is constant."); + System.out.println(ystrs[0] + " |--> " + trg); + System.out.println(); + } + + boolean prefixed = AuxMath.isPrefixed(xstrs,ystrs); + if (prefixed) + { System.out.println(">>> Target is " + src + " + a prefix "); + String pref = AuxMath.commonPrefix(xstrs,ystrs); + if (pref != null) + { System.out.println("\"" + pref + "\" + " + src + " |--> " + trg); } + } + + boolean suffixed = AuxMath.isSuffixed(xstrs,ystrs); + if (suffixed) + { System.out.println(">>> Target is " + src + " + a suffix "); + String pref = AuxMath.commonSuffix(xstrs,ystrs); + if (pref != null) + { System.out.println(src + " + \"" + pref + "\" |--> " + trg); } + } + + boolean uppercased = AuxMath.isUpperCased(xstrs,ystrs); + if (uppercased) + { System.out.println(">>> Target is " + src + " uppercased "); + System.out.println(src + "->toUpperCase() |--> " + trg); + } + + boolean lowercased = AuxMath.isLowerCased(xstrs,ystrs); + if (lowercased) + { System.out.println(">>> Target is " + src + " lowercased "); + System.out.println(src + "->toLowerCase() |--> " + trg); + } + + boolean reversed = AuxMath.isReversed(xstrs,ystrs); + if (reversed) + { System.out.println(">>> Target is " + src + " reversed "); + System.out.println(src + "->reverse() |--> " + trg); + } + } + + if (!valid && src.isSequence() && trg.isSequence()) + { if (AuxMath.isConstantSequence(yvect)) + { System.out.println(">>> " + trg + " is constant."); + System.out.println(yvect[0] + " |--> " + trg); + System.out.println(); + } + + + boolean prefixed = AuxMath.isPrefixedSequence(xvect, yvect, sent, tent, mod); + if (prefixed) + { System.out.println(">>> Target is " + src + " + a prefix "); + Vector pref = AuxMath.commonSequencePrefix(xvect,yvect); + if (pref != null) + { System.out.println(pref + "^" + src + " |--> " + trg); } + } + + boolean suffixed = AuxMath.isSuffixedSequence(xvect, yvect, sent, tent, mod); + if (suffixed) + { System.out.println(">>> Target is " + src + " + a suffix "); + Vector pref = AuxMath.commonSequenceSuffix(xvect,yvect); + if (pref != null) + { System.out.println(src + "^" + pref + " |--> " + trg); } + } + } + + if (!valid && src.isSet() && trg.isSet()) + { if (AuxMath.isConstantSet(yvect)) + { System.out.println(">>> " + trg + " is constant."); + System.out.println(yvect[0] + " |--> " + trg); + System.out.println(); + } + + + boolean subsetted = AuxMath.isSubsetSet(xvect, yvect, sent, tent, mod); + if (subsetted) + { System.out.println(">>> Target is " + src + " + some elements "); + Vector sadded = AuxMath.commonSubsetSet(xvect,yvect,sent,tent,mod); + if (sadded != null) + { System.out.println(src + "->union(" + sadded + ") |--> " + trg); } + } + } + + } } diff --git a/AuxMath.java b/AuxMath.java new file mode 100644 index 00000000..710e9c88 --- /dev/null +++ b/AuxMath.java @@ -0,0 +1,668 @@ +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.Comparator; +import java.util.Collections; +import java.util.Vector; + + +public class AuxMath +{ static double meanx = 0; + static double meany = 0; + static double sumprods = 0; + static double sumdiffxsq = 0; + static double sumdiffysq = 0; + + public static double to3dp(double val) + { int x = (int) Math.round(val*1000); + return x/1000.0; + } + + public static boolean isFunctional(double[] xs, double[] ys) + { // For each x : xs, only one y : ys + java.util.HashMap valueSets = new java.util.HashMap(); + + for (int i = 0; i < xs.length; i++) + { Double xval = new Double(xs[i]); + java.util.HashSet yvals = (java.util.HashSet) valueSets.get(xval); + if (yvals == null) + { yvals = new java.util.HashSet(); } + yvals.add(new Double(ys[i])); + valueSets.put(xval,yvals); + if (yvals.size() > 1) + { return false; } + // System.out.println(valueSets); + } + return true; + } + + public static boolean isFunctional(String[] xs, String[] ys) + { // For each x : xs, only one y : ys + java.util.HashMap valueSets = new java.util.HashMap(); + + for (int i = 0; i < xs.length; i++) + { java.util.HashSet yvals = (java.util.HashSet) valueSets.get(xs[i]); + if (yvals == null) + { yvals = new java.util.HashSet(); } + yvals.add(ys[i]); + valueSets.put(xs[i],yvals); + if (yvals.size() > 1) + { return false; } + // System.out.println(valueSets); + } + return true; + } + + public static boolean isConstant(double[] ys) + { if (ys.length > 1) + { double y0 = ys[0]; + for (int i = 1; i < ys.length; i++) + { if (ys[i] == y0) { } + else + { return false; } + } + return true; + } + return false; + } + + public static boolean isConstant(String[] ys) + { if (ys.length > 1) + { String y0 = ys[0]; + for (int i = 1; i < ys.length; i++) + { if (y0.equals(ys[i])) { } + else + { return false; } + } + return true; + } + return false; + } + + public static boolean isConstantSequence(Vector[] ys) + { if (ys.length > 1) + { Vector y0 = ys[0]; + for (int i = 1; i < ys.length; i++) + { if (y0.equals(ys[i])) { } + else + { return false; } + } + return true; + } + return false; + } + + public static boolean isConstantSet(Vector[] ys) + { if (ys.length > 1) + { Vector y0 = ys[0]; + for (int i = 1; i < ys.length; i++) + { if (y0.containsAll(ys[i]) && ys[i].containsAll(y0)) { } + else + { return false; } + } + return true; + } + return false; + } + + public static boolean allSubsets(Vector[] xs, Vector[] ys) + { for (int i = 0; i < xs.length && i < ys.length; i++) + { Vector xval = xs[i]; + Vector yval = ys[i]; + if (yval.containsAll(xval)) { } + else { return false; } + } + return true; + } + + public static double isExponential(double[] xs, double[] ys) + { // check if e^xs is linear with ys + double[] exs = new double[xs.length]; + double[] eys = new double[ys.length]; + for (int i = 0; i < xs.length; i++) + { // if (ys[i] <= 0) { return 0; } + // eys[i] = Math.log(ys[i]); + exs[i] = Math.exp(xs[i]); + } + + return linearCorrelation(exs,ys); + } + + public static void exponentialRelationship(String s, String t) + { double slope = AuxMath.linearSlope(); + double offset = AuxMath.linearOffset(); + System.out.println(slope + "*e->pow(" + s + ") + " + offset + " |--> " + t); + } + + public static double mean(double[] xs) + { double res = 0; + for (int i = 0; i < xs.length; i++) + { res = res + xs[i]; } + return res/xs.length; + } + + public static double linearCorrelation(double[] xs, double[] ys) + { if (ys.length < 3) + { System.err.println("Need 3 or more points to analyse linear correlation"); + return 0; + } + + meanx = mean(xs); + meany = mean(ys); + + sumprods = 0; + sumdiffxsq = 0; + sumdiffysq = 0; + + for (int i = 0; i < xs.length && i < ys.length; i++) + { double diffx = xs[i] - meanx; + double diffy = ys[i] - meany; + + sumprods = sumprods + diffx*diffy; + sumdiffxsq = sumdiffxsq + diffx*diffx; + sumdiffysq = sumdiffysq + diffy*diffy; + } + // System.out.println("sumprods = " + sumprods); + // System.out.println("xsq = " + sumdiffxsq); + // System.out.println("ysq = " + sumdiffysq); + + if (sumdiffxsq == 0 || sumdiffysq == 0) { return 0; } + + // double slope = sumprods/sumdiffxsq; + // System.out.println("Slope = " + slope); + // System.out.println("Offset = " + (meany - slope*meanx)); + return sumprods/Math.sqrt(sumdiffxsq*sumdiffysq); + } + + public static double linearSlope() + { if (sumdiffxsq != 0) + { return sumprods/sumdiffxsq; } + return 0; + } + + public static double linearOffset() + { double slope = sumprods/sumdiffxsq; + return meany - slope*meanx; + } + + public static boolean slopes(double[] ys) + { // y values in order of increasing x + + if (ys.length < 3) + { System.err.println("Need 3 or more points to analyse slopes"); + return false; + } + + int endpoint = ys.length-2; + int maxcount = 0; + int mincount = 0; + + double[] diffs = new double[ys.length-1]; + for (int i = 0; i < ys.length-1; i++) + { diffs[i] = ys[i+1] - ys[i]; } + + for (int j = 1; j < diffs.length; j++) + { if (diffs[j-1] < 0 && diffs[j] > 0) + { mincount++; } + else if (j+1 < diffs.length && diffs[j-1] < 0 && diffs[j] == 0 && diffs[j+1] > 0) + { mincount++; } + else if (diffs[j-1] > 0 && diffs[j] < 0) + { maxcount++; } + else if (j+1 < diffs.length && diffs[j-1] > 0 && diffs[j] == 0 && diffs[j+1] < 0) + { maxcount++; } + } + System.out.println(">> maxima = " + maxcount); + System.out.println(">> minima = " + mincount); + + if (maxcount == 1 && mincount == 0 && diffs[0] > 0 && diffs[endpoint] < 0) + { System.out.println("Could be -ve quadratic"); + return true; + } + else if (mincount == 1 && maxcount == 0 && diffs[0] < 0 && diffs[endpoint] > 0) + { System.out.println("Could be +ve quadratic"); + return true; + } + else if (mincount == 1 && maxcount == 1 & diffs[0] < 0 && diffs[endpoint] < 0) + { System.out.println("Could be -ve cubic"); + return true; + } + else if (mincount == 1 && maxcount == 1 && diffs[0] > 0 && diffs[endpoint] > 0) + { System.out.println("Could be +ve cubic"); + return true; + } + else if (mincount == 0 && maxcount == 0) + { // analyse the slope to see if polynomial or exponential + System.out.println("Increasing/decreasing function with no minima/maxima"); + } + else if (mincount > 1 && maxcount > 1) + { System.out.println("Multiple maxima and minima, could be trignometric"); } + + return false; + } + + public static boolean quadraticRelationship(double[] xs, double[] ys, + String s, String t) + { double[] xsq = new double[xs.length]; + for (int i = 0; i < xs.length; i++) + { xsq[i] = xs[i]*xs[i]; } + + if (xs.length < 3) + { System.out.println("ERROR: too few points to evaluate quadratic relationship -- need 3 datapoints"); + return false; + } + + boolean isOk = true; + + java.util.Set alphas = new java.util.HashSet(); + java.util.Set betas = new java.util.HashSet(); + double alpha = 0; + double beta = 0; + double gamma = 0; + + for (int i = 0; i+2 < xs.length && i+2 < ys.length; i++) + { double x1 = xs[i]; + double x1sq = xsq[i]; + double y1 = ys[i]; + + double x2 = xs[i+1]; + double x2sq = xsq[i+1]; + double y2 = ys[i+1]; + + double x3 = xs[i+2]; + double x3sq = xsq[i+2]; + double y3 = ys[i+2]; + + double divisor = (x1sq - x2sq)*(x3 - x2) + (x2sq - x3sq)*(x1 - x2); + // System.out.println("Divisor: " + divisor); + if (divisor == 0) + { System.out.println("This is not quadratic"); + return false; + } + + alpha = to3dp(((y1 - y2)*(x3 - x2) + (y2 - y3)*(x1 - x2))/divisor); + beta = -to3dp(((y1 - y2)*(x3sq - x2sq) + (y2 - y3)*(x1sq - x2sq))/divisor); + gamma = y1 - alpha*x1sq - beta*x1; + alphas.add(new Double(alpha)); + betas.add(new Double(beta)); + System.out.println("alpha = " + alpha + " beta = " + beta); + } + + if (alphas.size() == 1 && betas.size() == 1) + { System.out.println("Consistent with quadratic function.\n" + + "Mapping is " + alpha + "*" + s + "*" + s + " + " + + beta + "*" + s + " + " + gamma + " |--> " + t); + System.out.println(); + } + return (alphas.size() == 1 && betas.size() == 1); + + // For groups of 3 successive points, solve the quadratic equation + } + + public static boolean isUpperCased(String[] xs, String[] ys) + { for (int i = 0; i < xs.length && i < ys.length; i++) + { String xval = xs[i]; + String yval = ys[i]; + if (yval.equals(xval.toUpperCase())) { } + else + { return false; } + } + return true; + } + + public static boolean isLowerCased(String[] xs, String[] ys) + { for (int i = 0; i < xs.length && i < ys.length; i++) + { String xval = xs[i]; + String yval = ys[i]; + if (yval.equals(xval.toLowerCase())) { } + else + { return false; } + } + return true; + } + + public static boolean isPrefixed(String[] xs, String[] ys) + { for (int i = 0; i < xs.length && i < ys.length; i++) + { String xval = xs[i]; + String yval = ys[i]; + if (yval.endsWith(xval)) { } + else + { return false; } + } + return true; + } + + public static String commonPrefix(String[] xs, String[] ys) + { java.util.HashSet prefixes = new java.util.HashSet(); + String prefix = ""; + + for (int i = 0; i < xs.length && i < ys.length; i++) + { String xval = xs[i]; + String yval = ys[i]; + if (yval.endsWith(xval)) + { int j = yval.lastIndexOf(xval); + prefix = yval.substring(0,j); + // System.out.println(prefix); + prefixes.add(prefix); + } + else + { return null; } + } + + if (prefixes.size() == 1) + { return prefix; } + return null; + } + + public static boolean isSuffixed(String[] xs, String[] ys) + { for (int i = 0; i < xs.length && i < ys.length; i++) + { String xval = xs[i]; + String yval = ys[i]; + if (yval.startsWith(xval)) { } + else + { return false; } + } + return true; + } + + public static String commonSuffix(String[] xs, String[] ys) + { java.util.HashSet suffixes = new java.util.HashSet(); + String suffix = ""; + + for (int i = 0; i < xs.length && i < ys.length; i++) + { String xval = xs[i]; + String yval = ys[i]; + if (yval.startsWith(xval)) + { int j = xval.length(); + suffix = yval.substring(j,yval.length()); + // System.out.println(suffix); + suffixes.add(suffix); + } + else + { return null; } + } + + if (suffixes.size() == 1) + { return suffix; } + return null; + } + + public static boolean isEqualIgnoringCase(String[] xs, String[] ys) + { for (int i = 0; i < xs.length && i < ys.length; i++) + { String xval = xs[i]; + String yval = ys[i]; + if (yval.equalsIgnoreCase(xval)) { } + else + { return false; } + } + return true; + } + + public static boolean isReversed(String[] xs, String[] ys) + { for (int i = 0; i < xs.length && i < ys.length; i++) + { String xval = xs[i]; + String yval = ys[i]; + if (AuxMath.reverse(yval).equals(xval)) { } + else + { return false; } + } + return true; + } + + public static String reverse(String a) + { String res = ""; + for (int i = a.length() - 1; i >= 0; i--) + { res = res + a.charAt(i); } + return res; + } + + public static boolean isPrefixedSequence(Vector[] xs, Vector[] ys, String sent, String tent, ModelSpecification mod) + { for (int i = 0; i < xs.length && i < ys.length; i++) + { Vector xval = xs[i]; + Vector yval = ys[i]; + int xsize = xval.size(); + int ysize = yval.size(); + if (xsize < ysize) + { Vector ytail = new Vector(); + for (int j = (ysize-xsize); j < ysize; j++) + { ytail.add(yval.get(j)); } + + System.out.println(">> xval is: " + xval); + System.out.println(">> yval is: " + yval); + System.out.println(">> ytail is: " + ytail); + + if (mod.correspondingObjectSequences(sent,tent,xval,ytail)) { } + else + { return false; } + } + else + { return false; } + } + return true; + } + + public static Vector commonSequencePrefix(Vector[] xs, Vector[] ys) + { java.util.HashSet prefixes = new java.util.HashSet(); + Vector prefix = new Vector(); + + for (int i = 0; i < xs.length && i < ys.length; i++) + { Vector xval = xs[i]; + Vector yval = ys[i]; + int xsize = xval.size(); + int ysize = yval.size(); + if (xsize < ysize) + { Vector yfront = new Vector(); + for (int j = 0; j < (ysize-xsize); j++) + { yfront.add(yval.get(j)); } + prefixes.add(yfront); + prefix = yfront; + } + else + { return null; } + } + + if (prefixes.size() == 1) + { return prefix; } + return null; + } + + public static boolean isSuffixedSequence(Vector[] xs, Vector[] ys, String sent, String tent, ModelSpecification mod) + { for (int i = 0; i < xs.length && i < ys.length; i++) + { Vector xval = xs[i]; + Vector yval = ys[i]; + int xsize = xval.size(); + int ysize = yval.size(); + if (xsize < ysize) + { Vector yfront = new Vector(); + for (int j = 0; j < xsize; j++) + { yfront.add(yval.get(j)); } + + System.out.println(">> xval is: " + xval); + System.out.println(">> yval is: " + yval); + System.out.println(">> yfront is: " + yfront); + + if (mod.correspondingObjectSequences(sent,tent,xval,yfront)) { } + else + { return false; } + } + else + { return false; } + } + return true; + } + + public static Vector commonSequenceSuffix(Vector[] xs, Vector[] ys) + { java.util.HashSet suffixes = new java.util.HashSet(); + Vector suffix = new Vector(); + + for (int i = 0; i < xs.length && i < ys.length; i++) + { Vector xval = xs[i]; + Vector yval = ys[i]; + int xsize = xval.size(); + int ysize = yval.size(); + if (xsize < ysize) + { Vector ytail = new Vector(); + for (int j = xsize; j < ysize; j++) + { ytail.add(yval.get(j)); } + suffixes.add(ytail); + suffix = ytail; + } + else + { return null; } + } + + if (suffixes.size() == 1) + { return suffix; } + return null; + } + + public static boolean isSubsetSet(Vector[] xs, Vector[] ys, String sent, String tent, ModelSpecification mod) + { for (int i = 0; i < xs.length && i < ys.length; i++) + { Vector xval = xs[i]; + Vector yval = ys[i]; + int xsize = xval.size(); + int ysize = yval.size(); + if (xsize < ysize) + { Vector ytail = mod.correspondingObjectSubset(sent,tent,xval,yval); + if (ytail != null) + { System.out.println(">>> Corresponding objects of " + xval + " are " + ytail); } + else + { return false; } + } + else + { return false; } + } + return true; + } + + public static Vector commonSubsetSet(Vector[] xs, Vector[] ys, String sent, String tent, ModelSpecification mod) + { java.util.Set unionsets = new java.util.HashSet(); + java.util.Set added = new java.util.HashSet(); + + for (int i = 0; i < xs.length && i < ys.length; i++) + { Vector xval = xs[i]; + Vector yval = ys[i]; + int xsize = xval.size(); + int ysize = yval.size(); + if (xsize < ysize) + { Vector ytail = mod.correspondingObjectSubset(sent,tent,xval,yval); + if (ytail != null) + { java.util.HashSet yrem = new java.util.HashSet(); + yrem.addAll(yval); + yrem.removeAll(ytail); + System.out.println(">>> Added objects are " + yrem); + added = yrem; + unionsets.add(yrem); + } + else + { return null; } + } + else + { return null; } + } + + if (unionsets.size() == 1) + { Vector sourceadded = mod.getSourceObjects(sent,tent,added); + System.out.println("Mapping adds " + sourceadded + " to source collection"); + return sourceadded; + } + return null; + } + + public static void main(String[] args) + { double[] xs = {-2,-1,0,1,2,3}; + double[] ys = {11,5,3,5,11,21}; + + System.out.println(isFunctional(xs,ys)); + + System.out.println(quadraticRelationship(xs,ys,"s","t")); + + double[] xs2 = {-2,-1,0,1,2,3,4}; + double[] ys2 = {11,5,3,5,11,21,35}; + slopes(ys2); + + System.out.println(quadraticRelationship(xs2,ys2,"s","t")); + + double[] xss = {1,2,3,4,5,6}; + double[] yss = {1,2,6,24,120,720}; + double[] yss2 = {10,100,1000,10000,100000,1000000}; + + System.out.println(isFunctional(xss,yss)); + + double ecorr = isExponential(xss,yss); + System.out.println(ecorr); + + double ecorr2 = isExponential(xss,yss2); + System.out.println(ecorr2); + + double[] xn = {1,2,3,4,3,6}; + double[] yn = {1,2,6,24,120,720}; + + System.out.println(isFunctional(xn,yn)); + + String[] ss = {"ab", "bc", "cc"}; + String[] ts = {"ba", "cb", "cc"}; + + System.out.println(isFunctional(ss,ts)); + System.out.println(isConstant(ts)); + System.out.println(isReversed(ss,ts)); + + Vector sq1 = new Vector(); + sq1.add("a"); sq1.add("b"); + Vector sq2 = new Vector(); + sq2.add("c"); sq2.add("d"); + Vector[] xv = { sq1, sq2 }; + Vector sq3 = new Vector(); + sq3.add("a"); sq3.add("b"); + sq3.add("c"); sq3.add("d"); + sq3.add("e"); sq3.add("f"); + Vector[] yv = { sq1, sq3 }; + System.out.println(isConstantSequence(yv)); + System.out.println(allSubsets(xv,yv)); + + + + /* Double d1 = new Double(12); + Double d2 = new Double(12); + Double d3 = new Double(6); + Double d4 = new Double(18); + + List s1 = new ArrayList(); + s1.add(d1); + s1.add(d2); + s1.add(d3); + s1.add(d4); + List s2 = new ArrayList(); + s2.add(new Double(1)); + s2.add(new Double(3)); + s2.add(new Double(2)); + s2.add(new Double(4)); + List lll = SystemTypes.Ocl.sortedBy(s1,s2); + System.out.println(lll); + // 12, 6, 12, 18 + + Map f = new java.util.HashMap(); + f.put(d1, new Double(1)); + f.put(d2, new Double(3)); + f.put(d3, new Double(2)); + f.put(d4, new Double(4)); + + LComparator comp = new LComparator(f); + Collections.sort(s1,comp); + System.out.println(s1); */ + } + } + +/* class LComparator implements Comparator + { Map fmap; + + LComparator(Map f) + { fmap = f; } + + public int compare(Object x, Object y) + { Comparable c1 = (Comparable) fmap.get(x); + Comparable c2 = (Comparable) fmap.get(y); + return c1.compareTo(c2); + } + } */ + + diff --git a/BSystemTypes.java b/BSystemTypes.java index 31c9e4b1..e2dc32fc 100644 --- a/BSystemTypes.java +++ b/BSystemTypes.java @@ -47,6 +47,12 @@ public class BSystemTypes extends BComponent public static java.util.Map collectDecs = new java.util.TreeMap(); public static Vector collectList = new Vector(); + public static java.util.Map anyOps = new java.util.TreeMap(); + public static java.util.Map anyCodes = new java.util.TreeMap(); + public static java.util.Map anyDecs = new java.util.TreeMap(); + public static Vector anyList = new Vector(); + + public BSystemTypes(String nme) { super(nme,new Vector()); clearVariables(); @@ -56,17 +62,28 @@ public BSystemTypes(String nme) public static void resetDesigns() { selectOps.clear(); selectCodes.clear(); selectList.clear(); selectDecs.clear(); + existsOps.clear(); existsCodes.clear(); existsList.clear(); + exists1Ops.clear(); exists1Codes.clear(); exists1List.clear(); + + exists1Decs.clear(); existsDecs.clear(); + forAllOps.clear(); forAllCodes.clear(); - forAllDecs.clear(); exists1Decs.clear(); existsDecs.clear(); - forAllList.clear(); + forAllDecs.clear(); forAllList.clear(); + + rejectOps.clear(); rejectCodes.clear(); rejectList.clear(); rejectDecs.clear(); + collectList.clear(); collectDecs.clear(); collectOps.clear(); collectCodes.clear(); + + anyList.clear(); anyDecs.clear(); + anyOps.clear(); anyCodes.clear(); + index = 0; } @@ -1084,6 +1101,144 @@ else if ("Set".equals(ename)) } } + public static String getAnyDefinitionCPP(Expression left, String lqf, + Expression exp, + String collectvar, java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "_s"; + lqf = "Controller::inst->get" + instances + "()"; + } + + + String ename; + Type e = left.getElementType(); + if (e == null) + { ename = "void"; } + else + { ename = e.getName(); } + + String tname = ename + "*"; + if (Type.isBasicType(e)) + { tname = e.getCPP("void*"); } + else if ("Sequence".equals(ename)) + { tname = e.getCPP(e.getElementType()); } + else if ("Set".equals(ename)) + { tname = e.getCPP(e.getElementType()); } + + String argtype1 = "vector<" + tname + ">"; + String argtype2 = "set<" + tname + ">"; + + Type re = left.getElementType(); + String restype = "void*"; + if (re != null) + { restype = re.getCPP(re.getElementType()); } + + String pp = "" + exp + " " + ename + "(" + signature + ")"; + String op = (String) anyOps.get(pp); + // But may be different left element type with same expression + + // System.out.println(">>> CPP Any definition " + op); + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (collectvar != null) + { var = collectvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (collectvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + String elem = exp.queryFormCPP(newenv,false); + + String res1 = " static " + restype + " any_" + oldindex + + "(" + argtype1 + "* _l"; + String res2 = " static " + restype + " any_" + oldindex + + "(" + argtype2 + "* _l"; + + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + String partype = par.getType().getCPP(par.getElementType()); + res1 = res1 + ", " + partype + " " + par.getName(); + res2 = res2 + ", " + partype + " " + par.getName(); + } + + res1 = res1 + ")\n"; + + if (ename.equals("int")) // for Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormCPP(env,false); + String endexpqf = endexp.queryFormCPP(env,false); + String inttest = exp.queryFormCPP(env,false); + res1 = res1 + " { // Implements: " + left + "->any(" + var + "|" + exp + ")\n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { return " + var + "; } }\n"; + res1 = res1 + " return 0;\n }"; + + anyList.add(pp); + anyOps.put(pp,res1); + // anyDecs.put(pp,decl1); + anyCodes.put(pp,"" + oldindex); + + System.out.println(">>> CPP Any definition " + res1); + + return "any_" + oldindex + "(NULL)"; + } + } + } + + res1 = res1 + + " { // Implements: " + left + "->any( " + var + " | " + exp + " )\n" + + " " + restype + " _result_" + oldindex + + " = NULL;\n" + + " for (int _i = 0; _i < _l->size(); _i++)\n" + + " { " + tname + " " + var + " = (*_l)[_i];\n"; + + res2 = res2 + ")\n"; + res2 = res2 + " { " + restype + " _result_" + oldindex + + " = NULL;\n" + + " for (" + argtype2 + "::iterator _i = _l->begin(); _i != _l->end(); ++_i)\n" + + " { " + tname + " " + var + " = *_i;\n"; + + + res1 = res1 + " if (" + elem + ") { return " + var + "; }\n"; + res1 = res1 + " }\n"; + res1 = res1 + " return _result_" + oldindex + ";\n }"; + + res2 = res2 + " if (" + elem + ") { return " + var + "; }\n"; + res2 = res2 + " }\n"; + res2 = res2 + " return _result_" + oldindex + ";\n }"; + + anyList.add(pp); + anyOps.put(pp,res1 + "\n\n" + res2); + anyCodes.put(pp,"" + oldindex); + + System.out.println(">>> CPP Any definition " + res1 + "\n\n" + res2); + + + return "any_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) anyCodes.get(pp); + return "any_" + ind + "(" + lqf + ")"; + } + } + // distinguish cases where elem is an object and primitive: wrap(exp.getType(), public static String getRejectDefinition(Expression left, String lqf, @@ -1512,123 +1667,669 @@ else if (ename.equals("boolean")) res = res + " if (" + test + ") { } \n" + " else { _results_" + oldindex + ".Add(" + var + "); }\n"; res = res + " }\n"; - res = res + " return _results_" + oldindex + ";\n }"; + res = res + " return _results_" + oldindex + ";\n }"; + + rejectList.add(pp); + rejectOps.put(pp,res); + rejectCodes.put(pp,"" + oldindex); + + return "reject_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) rejectCodes.get(pp); + return "reject_" + ind + "(" + lqf + ")"; + } + } + + public static String getRejectDefinitionCPP(Expression left, String lqf, + Expression pred, String selectvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (Expression.isSimpleEntity(left)) + { BasicExpression lbe = (BasicExpression) left; + String lbedata = lbe.data; + String instances = lbedata.toLowerCase() + "_s"; + lqf = "Controller::inst->get" + instances + "()"; + } + + String ename; + Type e = left.getElementType(); + if (e == null) + { ename = "void"; } + else + { ename = e.getName(); } + + String tname = ename + "*"; + /* if (Type.isBasicType(e)) + { tname = e.getCPP("void*"); } + else if ("Sequence".equals(ename)) + { tname = "vector*"; } + else if ("Set".equals(ename)) + { tname = "set*"; } */ + if (e != null) + { tname = e.getCPP(e.getElementType()); } + + String restype1 = "set<" + tname + ">"; + String addop1 = "insert"; + String restype2 = "vector<" + tname + ">"; + String addop2 = "push_back"; + + // System.out.println(left + " element type is " + e); + + String pp = "" + pred + " " + ename + "(" + signature + ")"; + String op = (String) rejectOps.get(pp); + // But may be different left element type with same pred + + if (op == null) + { // add new definitions + + int oldindex = index; + index++; + + String var; + if (selectvar != null) + { var = selectvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (selectvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res1 = " static " + restype1 + "* select_" + oldindex + "(" + restype1 + "* _l"; + String res2 = " static " + restype2 + "* select_" + oldindex + "(" + restype2 + "* _l"; + + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + String cpppt = par.getType().getCPP(par.getElementType()); + res1 = res1 + ", " + cpppt + " " + par.getName(); + res2 = res2 + ", " + cpppt + " " + par.getName(); + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res1 = res1 + ")\n"; + res1 = res1 + " { // implements: " + left + "->reject( " + var + " | " + pred + " )\n" + + " " + restype1 + "* _results_" + oldindex + " = new " + restype1 + "();\n" + + " for (" + restype1 + "::iterator _i = _l->begin(); _i != _l->end(); ++_i)\n" + + " { " + tname + " " + var + " = *_i;\n"; + res2 = res2 + ")\n"; + res2 = res2 + " { " + restype2 + "* _results_" + oldindex + " = new " + restype2 + "();\n" + + " for (" + restype2 + "::iterator _i = _l->begin(); _i != _l->end(); ++_i)\n" + + " { " + tname + " " + var + " = *_i;\n"; + + String test = pred.queryFormCPP(newenv,false); + res1 = res1 + " if (" + test + ") { }\n" + + " else { _results_" + oldindex + "->" + addop1 + "(" + var + "); }\n"; + res1 = res1 + " }\n"; + res1 = res1 + " return _results_" + oldindex + ";\n }"; + res2 = res2 + " if (" + test + ") { }\n" + + " else { _results_" + oldindex + "->" + addop2 + "(" + var + "); }\n"; + res2 = res2 + " }\n"; + res2 = res2 + " return _results_" + oldindex + ";\n }"; + + String res = res1 + "\n\n" + res2; + + rejectList.add(pp); + rejectOps.put(pp,res); + rejectCodes.put(pp,"" + oldindex); + + return "reject_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) rejectCodes.get(pp); + return "reject_" + ind + "(" + lqf + ")"; + } + } + + // For: left->any(pred) + public static String getAnyDefinition(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (left == null) + { System.err.println("!!!! Null quantifier range: " + lqf + "->any(" + + exvar + "|" + pred + ")"); + return "/* error in ->any */"; + } + + if (Expression.isSimpleEntity(left)) + { BasicExpression bel = (BasicExpression) left; + String instances = bel.data.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String ename; + Type e = left.getElementType(); // left is null. + if (e == null) + { ename = "Object"; } + else if ("Set".equals(e.getName()) || "Sequence".equals(e.getName())) + { ename = "List"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapper(); } + + String pp = lqf + " " + pred + " " + tname + "(" + signature + ")"; + String op = (String) anyOps.get(pp); + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static " + tname + " any_" + oldindex + "(List _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + if (partype != null) + { res = res + ", " + partype.getJava() + " " + par.getName(); } + else + { res = res + ", Object " + par.getName(); } + + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryForm(env,false); + String endexpqf = endexp.queryForm(env,false); + String inttest = pred.queryForm(env,false); + res = res + " { \n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { return new Integer(" + var + "); } }\n"; + res = res + " return null;\n }"; + + anyList.add(pp); + anyOps.put(pp,res); + anyCodes.put(pp,"" + oldindex); + return "any_" + oldindex + "(null)"; + } + } + } + + + res = res + " { // Implements: " + left + "->any(" + var + "|" + pred + ")\n" + + " for (int _i = 0; _i < _l.size(); _i++)\n"; + if ("int".equals(ename) || "Integer".equals(tname)) + { res = res + + " { int " + var + " = ((Integer) _l.get(_i)).intValue();\n"; + } + else if ("double".equals(ename)) + { res = res + + " { double " + var + " = ((Double) _l.get(_i)).doubleValue();\n"; + } + else if (ename.equals("boolean")) + { res = res + + " { boolean " + var + " = ((Boolean) _l.get(_i)).booleanValue();\n"; + } + else if ("long".equals(ename)) + { res = res + + " { long " + var + " = ((Long) _l.get(_i)).longValue();\n"; + } + else + { res = res + + " { " + tname + " " + var + " = (" + tname + ") _l.get(_i);\n"; + } + + + + String test = pred.queryForm(newenv,false); + res = res + " if (" + test + ")\n" + + " { return (" + tname + ") _l.get(_i); }\n"; + res = res + " }\n"; + res = res + " return null;\n }"; + + anyList.add(pp); + anyOps.put(pp,res); + anyCodes.put(pp,"" + oldindex); + + return "any_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) anyCodes.get(pp); + return "any_" + ind + "(" + lqf + ")"; + } + } + + // For: left->any(pred) + public static String getAnyDefinitionJava6(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (left == null) + { System.err.println("!!!! Null quantifier range: " + lqf + "->any(" + + exvar + "|" + pred + ")"); + return "/* error in ->any */"; + } + + if (Expression.isSimpleEntity(left)) + { BasicExpression bel = (BasicExpression) left; + String instances = bel.data.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String ename; + Type e = left.getElementType(); // left is null. + if (e == null) + { ename = "Object"; } + else if ("Set".equals(e.getName())) + { ename = "HashSet"; } + else if ("Sequence".equals(e.getName())) + { ename = "ArrayList"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapperJava6(); } + + String pp = lqf + " " + pred + " " + tname + "(" + signature + ")"; + String op = (String) anyOps.get(pp); + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static " + tname + " any_" + oldindex + "(Collection _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + if (partype != null) + { res = res + ", " + partype.getJava6() + " " + par.getName(); } + else + { res = res + ", Object " + par.getName(); } + + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormJava6(env,false); + String endexpqf = endexp.queryFormJava6(env,false); + String inttest = pred.queryFormJava6(env,false); + res = res + " { \n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { return new Integer(" + var + "); } }\n"; + res = res + " return null;\n }"; + + anyList.add(pp); + anyOps.put(pp,res); + anyCodes.put(pp,"" + oldindex); + return "any_" + oldindex + "(null)"; + } + } + } + + + res = res + " { // Implements: " + left + "->any(" + var + "|" + pred + ")\n" + + " for (Object _i : _l)\n"; + if ("int".equals(ename) || "Integer".equals(tname)) + { res = res + + " { int " + var + " = ((Integer) _i).intValue();\n"; + } + else if ("double".equals(ename)) + { res = res + + " { double " + var + " = ((Double) _i).doubleValue();\n"; + } + else if (ename.equals("boolean")) + { res = res + + " { boolean " + var + " = ((Boolean) _i).booleanValue();\n"; + } + else if ("long".equals(ename)) + { res = res + + " { long " + var + " = ((Long) _i).longValue();\n"; + } + else + { res = res + + " { " + tname + " " + var + " = (" + tname + ") _i;\n"; + } + + + + String test = pred.queryFormJava6(newenv,false); + res = res + " if (" + test + ")\n" + + " { return (" + tname + ") _i; }\n"; + res = res + " }\n"; + res = res + " return null;\n }"; + + anyList.add(pp); + anyOps.put(pp,res); + anyCodes.put(pp,"" + oldindex); + + return "any_" + oldindex + "(" + lqf + ")"; + } + else + { String ind = (String) anyCodes.get(pp); + return "any_" + ind + "(" + lqf + ")"; + } + } + + // For: left->any(pred) + public static String getAnyDefinitionJava7(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) + { String signature = Attribute.parList(pars); + + if (left == null) + { System.err.println("!!!! Null quantifier range: " + lqf + "->any(" + + exvar + "|" + pred + ")"); + return "/* error in ->any */"; + } + + if (Expression.isSimpleEntity(left)) + { BasicExpression bel = (BasicExpression) left; + String instances = bel.data.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; + } + + String ename; + Type e = left.getElementType(); // left is null. + if (e == null) + { ename = "Object"; } + else if ("Set".equals(e.getName())) + { ename = "HashSet"; } + else if ("Sequence".equals(e.getName())) + { ename = "ArrayList"; } + else + { ename = e.getName(); } + + String tname = ename; + if (ename.equals("int")) + { tname = "Integer"; } + else if (e != null) + { tname = e.typeWrapperJava7(); } + + String pp = lqf + " " + pred + " " + tname + "(" + signature + ")"; + String op = (String) anyOps.get(pp); + + if (op == null) + { // add new definitions + int oldindex = index; + index++; + + String var; + if (exvar != null) + { var = exvar; } + else + { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } + + java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); + if (exvar == null && e != null && e.isEntity()) + { newenv.put(ename,var); } + + String res = " public static " + tname + " any_" + oldindex + "(Collection<" + tname + "> _l"; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + if (partype != null) + { res = res + ", " + partype.getJava7() + " " + par.getName(); } + else + { res = res + ", Object " + par.getName(); } + + // if ("self".equals(par.getName())) + // { newenv.put(par.getType().getName(),"self"); } + } + res = res + ")\n"; + + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormJava7(env,false); + String endexpqf = endexp.queryFormJava7(env,false); + String inttest = pred.queryFormJava7(env,false); + res = res + " { \n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { return new Integer(" + var + "); } }\n"; + res = res + " return null;\n }"; + + anyList.add(pp); + anyOps.put(pp,res); + anyCodes.put(pp,"" + oldindex); + return "any_" + oldindex + "(null)"; + } + } + } + + + res = res + " { // Implements: " + left + "->any(" + var + "|" + pred + ")\n" + + " for (Object _i : _l)\n"; + if ("int".equals(ename) || "Integer".equals(tname)) + { res = res + + " { int " + var + " = ((Integer) _i).intValue();\n"; + } + else if ("double".equals(ename)) + { res = res + + " { double " + var + " = ((Double) _i).doubleValue();\n"; + } + else if (ename.equals("boolean")) + { res = res + + " { boolean " + var + " = ((Boolean) _i).booleanValue();\n"; + } + else if ("long".equals(ename)) + { res = res + + " { long " + var + " = ((Long) _i).longValue();\n"; + } + else + { res = res + + " { " + tname + " " + var + " = (" + tname + ") _i;\n"; + } + + + + String test = pred.queryFormJava7(newenv,false); + res = res + " if (" + test + ")\n" + + " { return (" + tname + ") _i; }\n"; + res = res + " }\n"; + res = res + " return null;\n }"; - rejectList.add(pp); - rejectOps.put(pp,res); - rejectCodes.put(pp,"" + oldindex); + anyList.add(pp); + anyOps.put(pp,res); + anyCodes.put(pp,"" + oldindex); - return "reject_" + oldindex + "(" + lqf + ")"; + return "any_" + oldindex + "(" + lqf + ")"; } else - { String ind = (String) rejectCodes.get(pp); - return "reject_" + ind + "(" + lqf + ")"; + { String ind = (String) anyCodes.get(pp); + return "any_" + ind + "(" + lqf + ")"; } } - - public static String getRejectDefinitionCPP(Expression left, String lqf, - Expression pred, String selectvar, - java.util.Map env, - Vector pars) + + // For: left->any(pred) + public static String getAnyDefinitionCSharp(Expression left, String lqf, + Expression pred, String exvar, + java.util.Map env, + Vector pars) { String signature = Attribute.parList(pars); - if (Expression.isSimpleEntity(left)) - { BasicExpression lbe = (BasicExpression) left; - String lbedata = lbe.data; - String instances = lbedata.toLowerCase() + "_s"; - lqf = "Controller::inst->get" + instances + "()"; + if (left == null) + { System.err.println("!!!! Null quantifier range: " + lqf + "->any(" + + exvar + "|" + pred + ")"); + return "/* error in ->any */"; + } + + if (Expression.isSimpleEntity(left)) + { BasicExpression bel = (BasicExpression) left; + String instances = bel.data.toLowerCase() + "s"; + lqf = "Controller.inst()." + instances; } String ename; Type e = left.getElementType(); if (e == null) - { ename = "void"; } - else - { ename = e.getName(); } - - String tname = ename + "*"; - /* if (Type.isBasicType(e)) - { tname = e.getCPP("void*"); } - else if ("Sequence".equals(ename)) - { tname = "vector*"; } - else if ("Set".equals(ename)) - { tname = "set*"; } */ - if (e != null) - { tname = e.getCPP(e.getElementType()); } + { ename = "object"; } + else if ("Set".equals(e.getName())) + { ename = "ArrayList"; } + else if ("Sequence".equals(e.getName())) + { ename = "ArrayList"; } + else + { ename = e.getName(); } - String restype1 = "set<" + tname + ">"; - String addop1 = "insert"; - String restype2 = "vector<" + tname + ">"; - String addop2 = "push_back"; - - // System.out.println(left + " element type is " + e); + String tname = ename; + if (ename.equals("String")) + { tname = "string"; } + else if (ename.equals("boolean")) + { tname = "bool"; } + + // if (ename.equals("int")) + // { tname = "Integer"; } + // else if (e != null) + // { tname = e.typeWrapperCSharp(); } - String pp = "" + pred + " " + ename + "(" + signature + ")"; - String op = (String) rejectOps.get(pp); - // But may be different left element type with same pred + String pp = lqf + " " + pred + " " + tname + "(" + signature + ")"; + String op = (String) anyOps.get(pp); if (op == null) { // add new definitions - int oldindex = index; index++; - + String var; - if (selectvar != null) - { var = selectvar; } + if (exvar != null) + { var = exvar; } else { var = ename.toLowerCase() + "_" + oldindex + "_xx"; } java.util.Map newenv = (java.util.Map) ((java.util.HashMap) env).clone(); - if (selectvar == null && e != null && e.isEntity()) + if (exvar == null && e != null && e.isEntity()) { newenv.put(ename,var); } - - String res1 = " static " + restype1 + "* select_" + oldindex + "(" + restype1 + "* _l"; - String res2 = " static " + restype2 + "* select_" + oldindex + "(" + restype2 + "* _l"; - + + String res = " public static " + tname + " any_" + oldindex + "(ArrayList _l"; for (int i = 0; i < pars.size(); i++) - { Attribute par = (Attribute) pars.get(i); - String cpppt = par.getType().getCPP(par.getElementType()); - res1 = res1 + ", " + cpppt + " " + par.getName(); - res2 = res2 + ", " + cpppt + " " + par.getName(); + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + if (partype != null) + { res = res + ", " + partype.getCSharp() + " " + par.getName(); } + else + { res = res + ", Object " + par.getName(); } + // if ("self".equals(par.getName())) // { newenv.put(par.getType().getName(),"self"); } } - res1 = res1 + ")\n"; - res1 = res1 + " { // implements: " + left + "->reject( " + var + " | " + pred + " )\n" + - " " + restype1 + "* _results_" + oldindex + " = new " + restype1 + "();\n" + - " for (" + restype1 + "::iterator _i = _l->begin(); _i != _l->end(); ++_i)\n" + - " { " + tname + " " + var + " = *_i;\n"; - res2 = res2 + ")\n"; - res2 = res2 + " { " + restype2 + "* _results_" + oldindex + " = new " + restype2 + "();\n" + - " for (" + restype2 + "::iterator _i = _l->begin(); _i != _l->end(); ++_i)\n" + - " { " + tname + " " + var + " = *_i;\n"; + res = res + ")\n"; - String test = pred.queryFormCPP(newenv,false); - res1 = res1 + " if (" + test + ") { }\n" + - " else { _results_" + oldindex + "->" + addop1 + "(" + var + "); }\n"; - res1 = res1 + " }\n"; - res1 = res1 + " return _results_" + oldindex + ";\n }"; - res2 = res2 + " if (" + test + ") { }\n" + - " else { _results_" + oldindex + "->" + addop2 + "(" + var + "); }\n"; - res2 = res2 + " }\n"; - res2 = res2 + " return _results_" + oldindex + ";\n }"; + if (ename.equals("int")) // quantification over Integer.subrange(st,en) + { if (left instanceof BasicExpression) + { BasicExpression leftbe = (BasicExpression) left; + Vector leftpars = leftbe.getParameters(); + if (leftpars != null && leftpars.size() >= 2 && "subrange".equals(leftbe.data)) + { Expression startexp = (Expression) leftpars.get(0); + Expression endexp = (Expression) leftpars.get(1); + String startexpqf = startexp.queryFormCSharp(env,false); + String endexpqf = endexp.queryFormCSharp(env,false); + String inttest = pred.queryFormCSharp(env,false); + res = res + " { \n" + + " for (int " + var + " = " + startexpqf + "; " + + var + " <= " + endexpqf + "; " + var + "++)\n" + + " { if (" + inttest + ") { return new Integer(" + var + "); } }\n"; + res = res + " return null;\n }"; - String res = res1 + "\n\n" + res2; + anyList.add(pp); + anyOps.put(pp,res); + anyCodes.put(pp,"" + oldindex); + return "any_" + oldindex + "(null)"; + } + } + } - rejectList.add(pp); - rejectOps.put(pp,res); - rejectCodes.put(pp,"" + oldindex); - return "reject_" + oldindex + "(" + lqf + ")"; + res = res + " { // Implements: " + left + "->any(" + var + "|" + pred + ")\n" + + " for (int _i = 0; _i < _l.Count; _i++)\n"; + if ("int".equals(ename) || "Integer".equals(tname)) + { res = res + + " { int " + var + " = (int) _l[_i];\n"; + } + else if ("double".equals(ename)) + { res = res + + " { double " + var + " = (double) _l[_i];\n"; + } + else if (ename.equals("boolean")) + { res = res + + " { bool " + var + " = (bool) _l[_i];\n"; + } + else if ("long".equals(ename)) + { res = res + + " { long " + var + " = (long) _l[_i];\n"; + } + else + { res = res + + " { " + tname + " " + var + " = (" + tname + ") _l[_i];\n"; + } + + + + String test = pred.queryFormCSharp(newenv,false); + res = res + " if (" + test + ")\n" + + " { return (" + tname + ") _l[_i]; }\n"; + res = res + " }\n"; + res = res + " return null;\n }"; + + anyList.add(pp); + anyOps.put(pp,res); + anyCodes.put(pp,"" + oldindex); + + return "any_" + oldindex + "(" + lqf + ")"; } else - { String ind = (String) rejectCodes.get(pp); - return "reject_" + ind + "(" + lqf + ")"; + { String ind = (String) anyCodes.get(pp); + return "any_" + ind + "(" + lqf + ")"; } } - // For: left->exists(pred) public static String getExistsDefinition(Expression left, String lqf, Expression pred, String exvar, @@ -3569,6 +4270,17 @@ public static String getRejectOps() return res; } + public static String getAnyOps() + { String res = ""; + System.out.println(">>> Any ops are: " + anyOps); + + for (int i = 0; i < anyList.size(); i++) + { Object k = anyList.get(i); + res = res + anyOps.get(k) + "\n\n"; + } + return res; + } + public static String getExistsOps() { String res = ""; // java.util.Iterator keys = existsOps.keySet().iterator(); @@ -3821,11 +4533,34 @@ public static String generateIntersectionMapOpCSharp() // for CSharp " { Hashtable res = new Hashtable(); \n" + " foreach (DictionaryEntry pair in m1) \n" + " { object key = pair.Key; \n" + - " if (m2.ContainsKey(key) && pair.Value.Equals(m2[key])) \n" + + " if (m2.ContainsKey(key) && pair.Value != null && pair.Value.Equals(m2[key])) \n" + " { res.Add(key, pair.Value); } \n" + " } \n" + " return res; \n" + - " } \n"; + " } \n\n"; + res = res + + " public static Hashtable restrictMap(Hashtable m1, ArrayList ks) \n" + + " { Hashtable res = new Hashtable(); \n" + + " foreach (DictionaryEntry pair in m1) \n" + + " { object key = pair.Key; \n" + + " if (ks.Contains(key)) \n" + + " { res.Add(key, pair.Value); } \n" + + " } \n" + + " return res; \n" + + " } \n\n"; + res = res + + " public static ArrayList mapKeys(Hashtable m) \n" + + " { ArrayList res = new ArrayList(); \n" + + " res.AddRange(m.Keys);\n" + + " return res; \n" + + " } \n\n"; + res = res + + " public static ArrayList mapValues(Hashtable m) \n" + + " { ArrayList res = new ArrayList(); \n" + + " res.AddRange(m.Values);\n" + + " return res; \n" + + " } \n\n"; + return res; } @@ -4007,6 +4742,52 @@ public static String generateIntersectionMapOpCPP() return res; } + public static String generateKeysMapOpCPP() + { String res = + " static set* keys(map* s)\n" + + " { map::iterator iter;\n" + + " set* res = new set();\n" + + " \n" + + " for (iter = s->begin(); iter != s->end(); ++iter)\n" + + " { string key = iter->first;\n" + + " res->insert(key);\n" + + " } \n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateValuesMapOpCPP() + { String res = + " static vector<_T>* values(map* s)\n" + + " { map::iterator iter;\n" + + " vector<_T>* res = new vector<_T>();\n" + + " \n" + + " for (iter = s->begin(); iter != s->end(); ++iter)\n" + + " { _T value = iter->second;\n" + + " res->push_back(value);\n" + + " } \n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateRestrictOpCPP() + { String res = + " static map* restrict(map* m1, set* ks)\n" + + " { map* res = new map();\n" + + " map::iterator iter;\n" + + " for (iter = m1->begin(); iter != m1->end(); ++iter)\n" + + " { string key = iter->first;\n" + + " if (ks->find(key) != ks->end())\n" + + " { (*res)[key] = iter->second; }\n" + + " } \n" + + " return res;\n" + + " }\n"; + return res; + } + + public static String generateTokeniseOpCPP() { String res = @@ -4082,6 +4863,10 @@ public static String generateAnyOp() " { if (v.size() == 0) { return null; }\n" + " return v.get(0);\n" + " }\n"; + res = res + " public static Object any(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return any(range); }\n\n"; return res; } @@ -4091,7 +4876,7 @@ public static String generateAnyOpJava6() " return null;\n" + " }\n"; return res; - } + } // map public static String generateAnyOpJava7() { String res = " public static T any(Collection v)\n" + @@ -4099,7 +4884,7 @@ public static String generateAnyOpJava7() " return null;\n" + " }\n"; return res; - } + } // map public static String generateAnyOpCSharp() { String res = " public static object any(ArrayList v)\n" + @@ -4107,7 +4892,7 @@ public static String generateAnyOpCSharp() " return v[0];\n" + " }\n"; return res; - } + } // map public static String generateAnyOpCPP() { String res = " static _T any(vector<_T>* v)\n" + @@ -4120,7 +4905,7 @@ public static String generateAnyOpCPP() " return *_pos;\n" + " }\n\n"; return res; - } + } // map public static String generateFirstOp() { String res = " public static Object first(List v)\n" + @@ -4266,6 +5051,11 @@ public static String generateMaxOp() // for Java res = res + " { Comparable e = (Comparable) l.get(i);\n"; res = res + " if (res.compareTo(e) < 0) { res = e; } }\n"; res = res + " return res; }\n"; + res = res + " public static Comparable max(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return max(range); }\n\n"; + return res; } @@ -4279,13 +5069,13 @@ public static String generateMaxOpJava6() // for Java6 res = res + " if (res.compareTo(e) < 0) { res = e; } }\n"; res = res + " return res; }\n"; return res; - } + } // map public static String generateMaxOpJava7() // for Java7 { String res = " public static T max(Collection l)\n"; res = res + " { return Collections.max(l); }\n"; return res; - } + } // map public static String generateMaxOpCSharp() // for CSharp { String res = " public static object max(ArrayList l)\n"; @@ -4297,7 +5087,7 @@ public static String generateMaxOpCSharp() // for CSharp res = res + " if (res.CompareTo(e) < 0) { res = e; } }\n"; res = res + " return res; }\n"; return res; - } + } // map public static String generateMaxOpCPP() // for C++ { String res = " static _T max(set<_T>* l)\n"; @@ -4305,7 +5095,7 @@ public static String generateMaxOpCPP() // for C++ res = res + " static _T max(vector<_T>* l)\n"; res = res + " { return *std::max_element(l->begin(), l->end()); }\n"; return res; - } + } // map public static String generateMinOp() { String res = " public static Comparable min(List l)\n"; @@ -4316,6 +5106,10 @@ public static String generateMinOp() res = res + " { Comparable e = (Comparable) l.get(i);\n"; res = res + " if (res.compareTo(e) > 0) { res = e; } }\n"; res = res + " return res; }\n"; + res = res + " public static Comparable min(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return min(range); }\n\n"; return res; } @@ -4329,13 +5123,13 @@ public static String generateMinOpJava6() res = res + " if (res.compareTo(e) > 0) { res = e; } }\n"; res = res + " return res; }\n"; return res; - } + } // map public static String generateMinOpJava7() // for Java7 - not needed. { String res = " public static T min(Collection l)\n"; res = res + " { return Collections.min(l); }\n"; return res; - } + } // map public static String generateMinOpCSharp() { String res = " public static object min(ArrayList l)\n"; @@ -4347,7 +5141,7 @@ public static String generateMinOpCSharp() res = res + " if (res.CompareTo(e) > 0) { res = e; } }\n"; res = res + " return res; }\n"; return res; - } + } // map public static String generateMinOpCPP() // for C++ { String res = " static _T min(set<_T>* l)\n"; @@ -4355,7 +5149,7 @@ public static String generateMinOpCPP() // for C++ res = res + " static _T min(vector<_T>* l)\n"; res = res + " { return *std::min_element(l->begin(), l->end()); }\n"; return res; - } + } // map public static String generateBeforeOp() { String res = " public static String before(String s, String sep)\n" + @@ -5100,8 +5894,25 @@ public static String generateSumOps() " { Object x = a.get(i); \n" + " sum = sum + x; }\n" + " return sum; }\n\n"; - return res; - } + res = res + " public static int sumint(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return sumint(range); }\n\n"; + res = res + " public static double sumdouble(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return sumdouble(range); }\n\n"; + res = res + " public static long sumlong(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return sumlong(range); }\n\n"; + res = res + " public static String sumString(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return sumString(range); }\n\n"; + return res; + } + public static String generatePrdOps() { String res = " public static int prdint(List a)\n" + @@ -5125,6 +5936,18 @@ public static String generatePrdOps() " if (x != null) { res *= x.longValue(); }\n" + " }\n" + " return res; }\n\n"; + res = res + " public static int prdint(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return prdint(range); }\n\n"; + res = res + " public static double prddouble(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return prddouble(range); }\n\n"; + res = res + " public static long prdlong(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return prdlong(range); }\n\n"; return res; } @@ -5157,7 +5980,7 @@ public static String generateSumOpsJava6() " { sum = sum + x; }\n" + " return sum; }\n\n"; return res; - } + } // and for maps public static String generatePrdOpsJava6() { String res = " public static int prdint(Collection a)\n" + @@ -5182,7 +6005,7 @@ public static String generatePrdOpsJava6() " } \n" + " return prd; }\n\n"; return res; - } + } // maps public static String generateSumOpsJava7() @@ -5210,7 +6033,7 @@ public static String generateSumOpsJava7() " { sum = sum + x; }\n" + " return sum; }\n\n"; return res; - } + } // maps public static String generatePrdOpsJava7() { String res = " public static int prdint(Collection a)\n" + @@ -5232,7 +6055,7 @@ public static String generatePrdOpsJava7() " } \n" + " return prd; }\n\n"; return res; - } + } // maps public static String generateSumOpsCSharp() @@ -5264,7 +6087,7 @@ public static String generateSumOpsCSharp() " sum = sum + x; }\n" + " return sum; }\n\n"; return res; - } + } // maps public static String generatePrdOpsCSharp() { String res = " public static int prdint(ArrayList a)\n" + @@ -5289,7 +6112,7 @@ public static String generatePrdOpsCSharp() " } \n" + " return _prd; }\n\n"; return res; - } + } // maps public static String generateSumOpsCPP() { String res = " static string sumString(vector* a)\n" + @@ -5315,7 +6138,7 @@ public static String generateSumOpsCPP() " { _sum += *_pos; }\n" + " return _sum; }\n\n"; return res; - } + } // maps public static String generatePrdOpsCPP() { String res = " static _T prd(vector<_T>* a)\n" + @@ -5330,7 +6153,7 @@ public static String generatePrdOpsCPP() " { _prd *= *_pos; }\n" + " return _prd; }\n\n"; return res; - } + } // maps public static String generateClosureOps(Vector assocs) { String res = ""; @@ -5392,7 +6215,12 @@ public static String generateAsSetOp() " else { res.add(obj); }\n" + " } \n" + " return res; \n" + - " }\n"; + " }\n"; + res = res + " public static List asSet(Map m)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return asSet(range); }\n\n"; + return res; } @@ -5407,7 +6235,7 @@ public static String generateAsSetOpCSharp() " return res; \n" + " }\n"; return res; - } + } // and map public static String generateSortOp() { String res = " public static List sort(final List a)\n" + @@ -6239,8 +7067,12 @@ public static String countOp() " else if (obj != null && obj.equals(l.get(_i))) { res++; } \n" + " }\n" + " return res; \n" + - " }\n\n" + - " public static int count(String s, String x)\n" + + " }\n\n"; + res = res + " public static int count(Map m, Object obj)\n" + + " { List range = new Vector();\n" + + " range.addAll(m.values());\n" + + " return count(range,obj); }\n\n"; + res = res + " public static int count(String s, String x)\n" + " { int res = 0; \n" + " if (\"\".equals(s)) { return res; }\n" + " int ind = s.indexOf(x); \n" + @@ -6284,7 +7116,7 @@ public static String countOpJava6() " return res;\n" + " }\n\n"; return res; - } + } // map case public static String countOpJava7() { String res = @@ -6306,7 +7138,7 @@ public static String countOpJava7() " return res;\n" + " }\n\n"; return res; - } + } // map case public static String countOpCSharp() { String res = @@ -6334,7 +7166,7 @@ public static String countOpCSharp() " return res;\n" + " }\n\n"; return res; - } + } // maps public static String countOpCPP() { String res = @@ -6359,7 +7191,7 @@ public static String countOpCPP() " return res;\n" + " }\n\n"; return res; - } + } // maps public static String charactersOp() { String res = @@ -7340,7 +8172,20 @@ public static String generateIntersectionMapOp() " \n" + " for (int x = 0; x < keys.size(); x++)\n" + " { Object key = keys.get(x);\n" + - " if (m2.containsKey(key) && m1.get(key).equals(m2.get(key)))\n" + + " if (m2.containsKey(key) && m1.get(key) != null && m1.get(key).equals(m2.get(key)))\n" + + " { res.put(key,m1.get(key)); }\n" + + " } \n" + + " return res;\n" + + " }\n\n"; + res = res + + " public static Map restrictMap(Map m1, Vector ks) \n" + + " { Vector keys = new Vector();\n" + + " keys.addAll(m1.keySet());\n" + + " Map res = new HashMap();\n" + + " \n" + + " for (int x = 0; x < keys.size(); x++)\n" + + " { Object key = keys.get(x);\n" + + " if (ks.contains(key))\n" + " { res.put(key,m1.get(key)); }\n" + " } \n" + " return res;\n" + @@ -7358,6 +8203,41 @@ public static String generateIncludingMapOpJava7() return res; } + public static String generateIncludesAllMapOpJava7() + { String res = " public static boolean includesAllMap(Map sup, Map sub)\n" + + " { Set keys = sub.keySet();\n" + + " \n" + + " for (D key : keys)\n" + + " { if (sup.containsKey(key))\n" + + " { if (sub.get(key).equals(sup.get(key)))\n" + + " {}\n" + + " else\n" + + " { return false; }\n" + + " }\n" + + " else \n" + + " { return false; }\n" + + " } \n" + + " return true;\n" + + " }\n"; + return res; + } + + public static String generateExcludesAllMapOpJava7() + { String res = + " public static boolean excludesAllMap(Map sup, Map sub)\n" + + " { Set keys = sub.keySet();\n" + + " \n" + + " for (D key : keys)\n" + + " { if (sup.containsKey(key))\n" + + " { if (sub.get(key).equals(sup.get(key)))\n" + + " { return false; }\n" + + " }\n" + + " } \n" + + " return true;\n" + + " }\n"; + return res; + } + public static String generateExcludeAllMapOpJava7() { String res = " public static Map excludeAllMap(Map m1, Map m2)\n" + @@ -7424,10 +8304,22 @@ public static String generateIntersectionMapOpJava7() " Set keys = m1.keySet(); \n" + " \n" + " for (D key : keys)\n" + - " { if (m2.containsKey(key) && m1.get(key).equals(m2.get(key)))\n" + + " { if (m2.containsKey(key) && m1.get(key) != null && m1.get(key).equals(m2.get(key)))\n" + " { res.put(key,m1.get(key)); }\n" + " } \n" + " return res;\n" + + " }\n\n"; + res = res + + " public static Map restrictMap(Map m1, Set ks) \n" + + " { Set keys = new HashSet();\n" + + " keys.addAll(m1.keySet());\n" + + " Map res = new HashMap();\n" + + " \n" + + " for (D key : keys)\n" + + " { if (ks.contains(key))\n" + + " { res.put(key,m1.get(key)); }\n" + + " } \n" + + " return res;\n" + " }\n"; return res; } diff --git a/BasicExpression.java b/BasicExpression.java index 6e7082cc..ab5e527e 100644 --- a/BasicExpression.java +++ b/BasicExpression.java @@ -68,6 +68,7 @@ class BasicExpression extends Expression elementType = new Type(e); type = new Type("Sequence",null); type.setElementType(elementType); + multiplicity = ModelElement.MANY; entity = e; } @@ -81,6 +82,7 @@ class BasicExpression extends Expression elementType = new Type(e); type = elementType; entity = e; + multiplicity = ModelElement.ONE; } BasicExpression(Type t, String ex) @@ -90,8 +92,11 @@ class BasicExpression extends Expression } data = ex; umlkind = VARIABLE; - elementType = t.getElementType(); type = t; + if (t != null) + { multiplicity = t.typeMultiplicity(); + elementType = t.getElementType(); + } } BasicExpression(String v, Expression e) @@ -103,6 +108,8 @@ class BasicExpression extends Expression umlkind = VARIABLE; type = e.elementType; entity = e.entity; + if (type != null) + { multiplicity = type.typeMultiplicity(); } } BasicExpression(Attribute att) @@ -129,6 +136,7 @@ class BasicExpression extends Expression umlkind = VALUE; elementType = new Type("int",null); type = new Type("int",null); + multiplicity = ModelElement.ONE; } BasicExpression(long i) @@ -136,6 +144,7 @@ class BasicExpression extends Expression umlkind = VALUE; elementType = new Type("long",null); type = new Type("long",null); + multiplicity = ModelElement.ONE; } BasicExpression(double d) @@ -143,6 +152,7 @@ class BasicExpression extends Expression umlkind = VALUE; elementType = new Type("double",null); type = new Type("double",null); + multiplicity = ModelElement.ONE; } BasicExpression(boolean b) @@ -150,6 +160,7 @@ class BasicExpression extends Expression umlkind = VALUE; elementType = new Type("boolean",null); type = new Type("boolean",null); + multiplicity = ModelElement.ONE; } BasicExpression(Association ast) @@ -218,11 +229,30 @@ else if (entity.hasDefinedRole(data)) BasicExpression(Type t) { data = t.getName(); + if ("Set".equals(data) || "Sequence".equals(data)) + { Type tp = t.getElementType(); + if (tp != null && tp.isEntity()) + { BasicExpression eexp = new BasicExpression(tp.getEntity()); + data = "subcollections"; + objectRef = eexp; + umlkind = FUNCTION; + } + else + { data = data + "(" + tp.getName() + ")"; + umlkind = TYPE; + } + } + else if ("Set".equals(data) || "Sequence".equals(data)) + { Type tp = t.getElementType(); + if (tp != null) + { data = data + "(" + tp.getName() + ")"; } + umlkind = TYPE; + } multiplicity = ModelElement.MANY; type = new Type("Set", null); type.setElementType(t); elementType = t; - umlkind = TYPE; + } public Expression getObjectRef() @@ -401,7 +431,7 @@ public Expression testTraceRelationWhen(Vector entities, Vector bound) t = pivot.getElementType(); } - System.out.println("PIVOT for " + this + " is: " + pivot); + // System.out.println("PIVOT for " + this + " is: " + pivot); Entity pivotEntity = t.getEntity(); Association ast = pivotEntity.getRole("traces$" + data + "$" + pivot.getName()); @@ -446,12 +476,15 @@ public Expression checkWhen(Vector entities, Vector bound) // String var = data.toLowerCase() + "$x"; String traceop = data + "$trace"; BasicExpression varexp = new BasicExpression(var); + varexp.setUmlKind(VARIABLE); + Entity ent = (Entity) ModelElement.lookupByName(traceop, entities); // or of the use case? Or relation doms? Expression pred = new BasicExpression(true); if (ent == null) { return pred; } + BasicExpression eexp = new BasicExpression(ent); BinaryExpression dran = new BinaryExpression(":", varexp, eexp); @@ -625,7 +658,7 @@ public boolean isQualified() } // Or its type is a map ... public boolean isZeroOneRole() - { if (umlkind == ROLE) + { if (umlkind == ROLE || umlkind == ATTRIBUTE) { Association ast = entity.getDefinedRole(data); if (ast != null && ast.getCard2() == ModelElement.ZEROONE) { return true; } @@ -633,6 +666,8 @@ public boolean isZeroOneRole() return false; } + // public boolean isZeroOne() + // { return lower == 0 && upper == 1; } public boolean isRuleCall(Vector rules) @@ -2348,7 +2383,7 @@ public boolean typeCheck(final Vector types, final Vector entities, if ("self".equals(data)) { if (contexts.size() == 0) { System.err.println("ERROR: Invalid occurrence of self, not in instance context"); - JOptionPane.showMessageDialog(null, "ERROR: Invalid occurrence of self, not in instance context", "Semantic error", JOptionPane.ERROR_MESSAGE); + // JOptionPane.showMessageDialog(null, "ERROR: Invalid occurrence of self, not in instance context", "Semantic error", JOptionPane.ERROR_MESSAGE); } else { if (contexts.size() > 1) @@ -3826,8 +3861,7 @@ else if (objectRef != null) if (objectRef == null) { if (umlkind == ATTRIBUTE || umlkind == ROLE) - { String nme = entity.getName(); - if (local) + { if (local) { if (arrayIndex != null) { // String etype = elementType + ""; String ind = arrayIndex.queryForm(env,local); @@ -3848,6 +3882,10 @@ else if (Type.isPrimitiveType(type)) return data; } + if (entity == null) { return data; } + + String nme = entity.getName(); + if (entity.isClassScope(data)) // entity cannot be an interface { if (arrayIndex != null) { String ind = arrayIndex.queryForm(env,local); @@ -4249,8 +4287,7 @@ else if (objectRef != null) if (objectRef == null) { if (umlkind == ATTRIBUTE || umlkind == ROLE) - { String nme = entity.getName(); - if (local) + { if (local) { if (arrayIndex != null) { String ind = arrayIndex.queryFormJava6(env,local); if (isQualified()) @@ -4268,6 +4305,10 @@ else if (Type.isPrimitiveType(type)) return data; } + if (entity == null) { return data; } + + String nme = entity.getName(); + if (entity.isClassScope(data)) // entity cannot be an interface { if (arrayIndex != null) { String ind = arrayIndex.queryFormJava6(env,local); @@ -4667,8 +4708,7 @@ else if (objectRef != null) if (objectRef == null) { if (umlkind == ATTRIBUTE || umlkind == ROLE) - { String nme = entity.getName(); - if (local) + { if (local) { if (arrayIndex != null) { String ind = arrayIndex.queryFormJava7(env,local); if (isQualified()) @@ -4686,6 +4726,10 @@ else if (Type.isPrimitiveType(type)) return data; } + if (entity == null) { return data; } + + String nme = entity.getName(); + if (entity.isClassScope(data)) // entity cannot be an interface { if (arrayIndex != null) { String ind = arrayIndex.queryFormJava7(env,local); @@ -5074,8 +5118,7 @@ else if (objectRef != null) if (objectRef == null) { if (umlkind == ATTRIBUTE || umlkind == ROLE) - { String nme = entity.getName(); - if (local) + { if (local) { if (arrayIndex != null) { String etype = type.getCSharp(); String ind = arrayIndex.queryFormCSharp(env,local); @@ -5090,6 +5133,10 @@ else if (objectRef != null) return data; } + if (entity == null) { return data; } + + String nme = entity.getName(); + if (entity.isClassScope(data)) // entity cannot be an interface { if (arrayIndex != null) { String ind = arrayIndex.queryFormCSharp(env,local); @@ -5443,8 +5490,7 @@ else if (objectRef != null) if (objectRef == null) { if (umlkind == ATTRIBUTE || umlkind == ROLE) - { String nme = entity.getName(); - if (local) + { if (local) { if (arrayIndex != null) { String etype = elementType + ""; String ind = arrayIndex.queryFormCPP(env,local); @@ -5459,6 +5505,10 @@ else if (objectRef != null) return data; } + if (entity == null) { return data; } + + String nme = entity.getName(); + if (entity.isClassScope(data)) { if (arrayIndex != null) { String etype = type.getCPP(elementType); @@ -5663,7 +5713,8 @@ public Statement generateDesignIn(Expression rhs) } else if (objectRef == null) { BinaryExpression inclu = new BinaryExpression("->including", this, rhs); - return new AssignStatement(this, inclu); } + return new AssignStatement(this, inclu); + } else if (objectRef.isMultiple()) { BasicExpression lhs = (BasicExpression) clone(); String v = Identifier.nextIdentifier("v_"); @@ -5674,9 +5725,18 @@ else if (objectRef.isMultiple()) Statement lp = Expression.iterationLoop(var, objectRef, update); return lp; } - else + else if (multiplicity == ModelElement.ZEROONE) + { Expression sizeiszero = new UnaryExpression("->isEmpty", this); + SequenceStatement skip = new SequenceStatement(); + SetExpression sett = new SetExpression(); + sett.addElement(rhs); + AssignStatement setthis = new AssignStatement(this, sett); + return new ConditionalStatement(sizeiszero, setthis, skip); + } + else { BinaryExpression inclu = new BinaryExpression("->including", this, rhs); - return new AssignStatement(this, inclu); } + return new AssignStatement(this, inclu); + } } @@ -7302,7 +7362,7 @@ else if (entity.hasStereotype("external")) if (local) { return data + ".add(" + val2 + ");"; } - // unordered roles: check not in first + // unordered and zero-one roles: check not in first return cont + ".add" + data + "(" + var + "," + val2 + ");"; } // no need to wrap -- val2 must be an object @@ -10881,6 +10941,39 @@ public Expression substituteEq(final String oldVar, return res; } // again, not if prestate + public Expression removePrestate() + { + BasicExpression res = (BasicExpression) clone(); + + res.prestate = false; + + if (arrayIndex != null) + { Expression newind = arrayIndex.removePrestate(); + res.arrayIndex = newind; + } + + Vector newpars = new Vector(); + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + newpars.add(par.removePrestate()); + } + res.parameters = newpars; + } + + if (objectRef == null) + { } + else + { res.objectRef = + objectRef.removePrestate(); + } + + res.setType(type); + res.setElementType(elementType); + + return res; + } + public Expression simplify(final Vector vars) { return simplify(); } @@ -11067,6 +11160,46 @@ public Vector allFeaturesUsedIn() return res; } // and from arrayIndex + public Vector allAttributesUsedIn() + { Vector res = new Vector(); + if ("self".equals(this + "")) + { return res; } + if ("super".equals(this + "")) + { return res; } + + if (umlkind == ATTRIBUTE || umlkind == ROLE) + { Vector path = getAttributePath(); + res.add(new Attribute(path)); + } + + /* + if (objectRef != null) + { res.addAll(objectRef.allFeaturesUsedIn()); } + if (arrayIndex != null) + { res.addAll(arrayIndex.allFeaturesUsedIn()); } + if (parameters != null) + { for (int i = 0; i < parameters.size(); i++) + { Expression par = (Expression) parameters.get(i); + res.addAll(par.allFeaturesUsedIn()); + } + } */ + + return res; + } // and from arrayIndex + + private Vector getAttributePath() + { Attribute att = new Attribute(this); + if (objectRef != null && (objectRef instanceof BasicExpression) && + !("self".equals(objectRef + ""))) + { Vector path = ((BasicExpression) objectRef).getAttributePath(); + path.add(att); + return path; + } + Vector res = new Vector(); + res.add(att); + return res; + } + public Vector allOperationsUsedIn() { Vector res = new Vector(); if (umlkind == UPDATEOP || umlkind == QUERY || isEvent) @@ -11346,7 +11479,7 @@ public Vector splitToCond0Cond1(Vector conds, Vector v1, Vector v2, Vector v3) // The following turns x : e & P & l = g & Q into [x,P,l,Q] in allvars - public Vector splitToCond0Cond1Pred(Vector conds, Vector pars, Vector qvars, Vector lvars, Vector allvars) + public Vector splitToCond0Cond1Pred(Vector conds, Vector pars, Vector qvars, Vector lvars, Vector allvars, Vector allpreds) { Expression cond0 = (Expression) conds.get(0); Expression cond1 = (Expression) conds.get(1); Vector res = new Vector(); @@ -11360,6 +11493,7 @@ public Vector splitToCond0Cond1Pred(Vector conds, Vector pars, Vector qvars, Vec res.add(cond0); res.add(c1); allvars.add(this); + allpreds.add(this); // System.out.println("Added condition: " + this); return res; @@ -11631,17 +11765,91 @@ public void changedEntityName(String oldN, String newN) } public String cg(CGSpec cgs) - { String etext = this + ""; + { String etext = (this + "").trim(); Vector args = new Vector(); + Vector eargs = new Vector(); + + if (umlkind == FUNCTION) + { // process as the corresponding unary or binary expression + if ("allInstances".equals(data)) + { args.add(objectRef + ""); + eargs.add(objectRef); + CGRule r = cgs.matchedBasicExpressionRule(this,etext); + // System.out.println(">> Matched rule: " + r + " to: " + etext + " with arguments= " + args); + String res = r.applyRule(args,eargs,cgs); + return res; + } + else if (parameters != null && parameters.size() == 0) + { UnaryExpression uexp = new UnaryExpression(this); + System.out.println(">> Converted basic expression " + this + + " to UnaryExpression " + uexp); + return uexp.cg(cgs); + } + else if (parameters != null && parameters.size() == 2) + { // case of x.insertAt(i,y) or s.subrange(x,y) + if ("Integer".equals(objectRef + "")) { } + else + { args.add(objectRef.cg(cgs)); } + args.add(((Expression) parameters.get(0)).cg(cgs)); + args.add(((Expression) parameters.get(1)).cg(cgs)); + eargs.add((Expression) parameters.get(0)); + eargs.add((Expression) parameters.get(1)); + CGRule r = cgs.matchedBasicExpressionRule(this,etext); + + if (r != null) + { System.out.println(">> Matched rule: " + r + " to: " + etext + " with arguments= " + args); + + String res = r.applyRule(args,eargs,cgs); + if (needsBracket) + { return "(" + res + ")"; } + else + { return res; } + } + } + else if (parameters != null && parameters.size() == 4 && "Integer".equals(objectRef + "")) + { // Integer.Sum(a,b,i,e), Integer.Prd(a,b,i,e) + args.add(((Expression) parameters.get(0)).cg(cgs)); + args.add(((Expression) parameters.get(1)).cg(cgs)); + args.add(((Expression) parameters.get(2)).cg(cgs)); + args.add(((Expression) parameters.get(3)).cg(cgs)); + eargs.add((Expression) parameters.get(0)); + eargs.add((Expression) parameters.get(1)); + eargs.add((Expression) parameters.get(2)); + eargs.add((Expression) parameters.get(3)); + CGRule r = cgs.matchedBasicExpressionRule(this,etext); + + if (r != null) + { // System.out.println(">> Matched rule: " + r + " to: " + etext + " with arguments= " + args); + + String res = r.applyRule(args,eargs,cgs); + if (needsBracket) + { return "(" + res + ")"; } + else + { return res; } + } + } + else if (parameters != null && parameters.size() == 1) + { BinaryExpression bexp = new BinaryExpression(this); + // System.out.println(">> Converted basic expression " + this + + // " to BinaryExpression " + bexp); + return bexp.cg(cgs); + } + + } + + if (arrayIndex != null) { BasicExpression arg = (BasicExpression) clone(); arg.arrayIndex = null; arg.parameters = null; args.add(arg.cg(cgs)); args.add(arrayIndex.cg(cgs)); + eargs.add(arg); + eargs.add(arrayIndex); } // assume parameters == null else if (objectRef != null) { args.add(objectRef.cg(cgs)); + eargs.add(objectRef); BasicExpression dataexp = (BasicExpression) clone(); dataexp.objectRef = null; if (parameters != null) @@ -11656,9 +11864,13 @@ else if (objectRef != null) dataexp.parameters = null; args.add(dataexp.cg(cgs)); args.add(parg); + eargs.add(dataexp); + eargs.add(new BasicExpression(parg)); } else - { args.add(dataexp.cg(cgs)); } + { args.add(dataexp.cg(cgs)); + eargs.add(dataexp); + } } else if (parameters != null) { String parg = ""; @@ -11671,16 +11883,37 @@ else if (parameters != null) } args.add(data); args.add(parg); + BasicExpression dataexp = (BasicExpression) clone(); + dataexp.objectRef = null; + dataexp.parameters = null; + eargs.add(dataexp); + eargs.add(new BasicExpression(parg)); } else - { args.add(etext); } + { args.add(etext); + eargs.add(this); + } // and cg of parameters CGRule r = cgs.matchedBasicExpressionRule(this,etext); - System.out.println(">> Matched rule: " + r + " arguments= " + args); + + // System.out.println(">>> Found basic expression rule: " + r + " for " + this); if (r != null) - { return r.applyRule(args); } + { + String res = r.applyRule(args,eargs,cgs); + if (needsBracket) + { return "(" + res + ")"; } + else + { return res; } + } + else + { r = cgs.matchedTextRule(etext); + if (r != null) + { System.out.println(">>> Found basic expression text rule: " + r + " for " + this); + return r.applyTextRule(etext); + } + } return etext; } diff --git a/BehaviouralFeature.java b/BehaviouralFeature.java index bbf382cc..ef6419c7 100644 --- a/BehaviouralFeature.java +++ b/BehaviouralFeature.java @@ -99,6 +99,79 @@ public void setActivity(Statement st) public void setResultType(Type t) { resultType = t; } + public String cg(CGSpec cgs) + { String etext = this + ""; + Vector args = new Vector(); + args.add(getName()); + Vector eargs = new Vector(); + eargs.add(this); + String pars = ""; + + if (parameters == null) {} + else if (parameters.size() == 0) {} + else + { Attribute p = (Attribute) parameters.get(0); + Vector partail = new Vector(); + partail.addAll(parameters); + partail.remove(0); + pars = p.cgParameter(cgs,partail); + } + args.add(pars); + eargs.add(parameters); + + if (resultType != null) + { args.add(resultType.cg(cgs)); + eargs.add(resultType); + } + else + { Type rt = new Type("void",null); + args.add(rt.cg(cgs)); + eargs.add(rt); + } + + if (pre != null) + { args.add(pre.cg(cgs)); + eargs.add(pre); + } + else + { BasicExpression pr = new BasicExpression(true); + args.add(pr.cg(cgs)); + eargs.add(pr); + } + + if (post != null) + { args.add(post.cg(cgs)); + eargs.add(post); + } + else + { BasicExpression pst = new BasicExpression(true); + args.add(pst.cg(cgs)); + eargs.add(pst); + } + + if (activity != null) + { String actres = activity.cg(cgs); + // System.out.println(">>> Activity result: " + actres); + args.add(actres); + eargs.add(activity); + } + else + { Statement nullstat = new SequenceStatement(); + args.add(nullstat.cg(cgs)); + eargs.add(nullstat); + } + // only one Operation rule? + // maybe for static/cached + + CGRule r = cgs.matchedOperationRule(this,etext); + if (r != null) + { // System.out.println(">>> Matched operation rule: " + r + " with args " + args); + return r.applyRule(args,eargs,cgs); + } + System.out.println("!!! No matching rule for operation " + getName()); + return etext; + } + public Vector getReadFrame() { if (readfr != null) { return readfr; } // to avoid recursion readfr = new Vector(); @@ -255,6 +328,9 @@ public Entity getEntity() public void setOwner(Entity ent) { entity = ent; } + public Entity getOwner() + { return entity; } + public void setUseCase(UseCase uc) { useCase = uc; } @@ -272,6 +348,12 @@ public void setPre(Expression p) public void setPost(Expression p) { post = p; } + public void setPrecondition(Expression p) + { pre = p; } + + public void setPostcondition(Expression p) + { post = p; } + public void setOrdered(boolean ord) { ordered = ord; } @@ -366,6 +448,12 @@ public Type getResultType() return (Type) resultType.clone(); } + public Type getType() + { if (resultType == null) + { return new Type("void",null); } + return (Type) resultType.clone(); + } + public Type getElementType() { if (elementType == null) { return null; } return (Type) elementType.clone(); @@ -540,11 +628,15 @@ public boolean typeCheck(Vector types, Vector entities, Vector contexts, Vector } // and the activity? // could deduce type and element type of result. - public static Vector reconstructParameters(String pars, + public static Vector reconstructParameters(String pars, + Vector types, Vector entities) + { return reconstructParameters(pars," ,:",types,entities); } + + public static Vector reconstructParameters(String pars,String seps, Vector types, Vector entities) { Vector parvals = new Vector(); Vector res = new Vector(); - StringTokenizer st = new StringTokenizer(pars," :,"); + StringTokenizer st = new StringTokenizer(pars,seps); while (st.hasMoreTokens()) { parvals.add(st.nextToken()); } @@ -556,15 +648,16 @@ public static Vector reconstructParameters(String pars, if (typ != null) { int bind = typ.indexOf("("); - if (bind > 0) // a set or sequence type - { String tparam = typ.substring(bind+1,typ.length() - 1); - // typ = typ.substring(0,bind); - // Entity eee = (Entity) ModelElement.lookupByName(tparam,entities); - // if (eee == null) - // { System.out.println("Error: invalid element type for operation: " + tparam); } - // else - // { elemType = new Type(eee); } - elemType = Type.getTypeFor(tparam,types,entities); + if (bind > 0) // a set, sequence or map type + { int cind = typ.indexOf(","); + if (cind > 0) + { String xparam = typ.substring(cind+1, typ.length() - 1); + elemType = Type.getTypeFor(xparam,types,entities); + } + else + { String tparam = typ.substring(bind+1,typ.length() - 1); + elemType = Type.getTypeFor(tparam,types,entities); + } } } @@ -580,7 +673,7 @@ public static Vector reconstructParameters(String pars, att.setElementType(elemType); t.setElementType(elemType); res.add(att); - System.out.println("Parameter " + var + " type " + t); + System.out.println(">>> Parameter " + var + " type " + t); } } return res; @@ -1884,6 +1977,8 @@ else if (activity != null) String resT = "void"; if (post == null) { return res; } // or use the SM if one exists + // if ("true".equals(post + "")) + // { return res; } if (resultType != null && !("void".equals(resultType.getName()))) { resT = resultType + ""; @@ -1894,10 +1989,10 @@ else if (activity != null) CreationStatement cs = new CreationStatement(resT, "result"); cs.setType(resultType); cs.setElementType(elementType); - Expression init = resultType.getDefaultValueExpression(elementType); - AssignStatement initialise = new AssignStatement(rbe, init); + // Expression init = resultType.getDefaultValueExpression(elementType); + // AssignStatement initialise = new AssignStatement(rbe, init); ((SequenceStatement) res).addStatement(cs); - ((SequenceStatement) res).addStatement(initialise); + // ((SequenceStatement) res).addStatement(initialise); rets = new ReturnStatement(rbe); } @@ -3474,7 +3569,7 @@ public Statement designQueryList(Vector postconds, String resT, "=>".equals(((BinaryExpression) next).operator)) { Statement elsepart = designQueryList(ptail,resT, env0,types,entities,atts); - ((IfStatement) fst).addCases((IfStatement) elsepart); + ((ConditionalStatement) fst).setElse(elsepart); // Statement.combineIfStatements(fst,elsepart); return fst; } @@ -3490,7 +3585,8 @@ public Statement designQueryList(Vector postconds, String resT, { Statement stat = designQueryList(ptail,resT, env0,types,entities,atts); SequenceStatement res = new SequenceStatement(); - res.addStatement(fst); res.addStatement(stat); + res.addStatement(fst); + res.addStatement(stat); return res; } // sequencing of fst and ptail } @@ -3544,13 +3640,13 @@ private Statement designBasicCase(Expression pst,String resT, java.util.Map env0 v0.add(betrue); v0.add(betrue.clone()); Vector splitante = test.splitToCond0Cond1Pred(v0,pars1,qvars1,lvars1,allvars,allpreds); - System.out.println(">>> Quantified local = " + qvars1 + " Let local = " + lvars1 + " All: " + allvars); + // System.out.println(">>> Quantified local = " + qvars1 + " Let local = " + lvars1 + " All: " + allvars); Expression ante1 = (Expression) splitante.get(0); Expression ante2 = (Expression) splitante.get(1); - System.out.println(">>> Variable quantifiers: " + ante1); - System.out.println(">>> Assumptions: " + ante2); + // System.out.println(">>> Variable quantifiers: " + ante1); + // System.out.println(">>> Assumptions: " + ante2); Statement ifpart = // new ImplicitInvocationStatement(be.right); designBasicCase(be.right, resT, env0, types, entities, atts); @@ -3558,7 +3654,7 @@ private Statement designBasicCase(Expression pst,String resT, java.util.Map env0 { Statement forloop = virtualCon.q2LoopsPred(allvars,qvars1,lvars1,ifpart); return forloop; } - return new IfStatement(test, ifpart); + return new ConditionalStatement(test, ifpart); } // But may be let definitions and local variables in test. else if ("=".equals(be.operator)) { Expression beleft = be.left; diff --git a/BinaryExpression.java b/BinaryExpression.java index 3f01cfbb..33fa8b1d 100644 --- a/BinaryExpression.java +++ b/BinaryExpression.java @@ -77,6 +77,16 @@ public BinaryExpression(Attribute att) type = new Type("boolean", null); } + public BinaryExpression(BasicExpression be) + { // obj.op(par) becomes obj->op(par) + + left = ((BasicExpression) be).getObjectRef(); + right = (Expression) ((Vector) be.getParameters()).get(0); + operator = "->" + be.getData(); + type = be.getType(); + elementType = be.getElementType(); + } + public void setLeft(Expression le) { left = le; } public void setRight(Expression re) { right = re; } @@ -93,6 +103,17 @@ public BinaryExpression(Attribute att) public Expression getKeyValue() { return keyValue; } + public BasicExpression getVariable() + { if (iteratorVariable == null) + { return null; } + BasicExpression res = new BasicExpression(iteratorVariable); + res.umlkind = VARIABLE; + res.setType(elementType); // except for any, when it is type + if ("|A".equals(operator)) + { res.setType(type); } + return res; + } + public Expression definedness() { Expression dl = left.definedness(); Expression dr = right.definedness(); @@ -191,6 +212,18 @@ public void setPre() right.setPre(); } + public Expression removePrestate() + { Expression dl = left.removePrestate(); + Expression dr = right.removePrestate(); + Expression res = new BinaryExpression(operator,dl,dr); + res.setType(type); + res.setElementType(elementType); + res.needsBracket = needsBracket; + return res; + } + + + public Expression checkConversions(Type propType, Type propElemType, java.util.Map interp) { /* if (type != null && type.isEntity()) { Entity ent = type.getEntity(); @@ -716,6 +749,15 @@ else if (operator.equals("|C")) basicString = rangestring + "->collect( " + ((BinaryExpression) left).left + " | " + right + " )"; } + else if (operator.equals("|A")) + { Expression range = ((BinaryExpression) left).right; + String rangestring = "" + range; + if (range.needsBracket) + { rangestring = "(" + rangestring + ")"; } + + basicString = rangestring + "->any( " + + ((BinaryExpression) left).left + " | " + right + " )"; + } else if (operator.equals("|R")) { Expression range = ((BinaryExpression) left).right; String rangestring = "" + range; @@ -739,7 +781,7 @@ else if (operator.equals("->includesAll") || operator.equals("->collect") || operator.equals("->hasPrefix") || "->isUnique".equals(operator) || operator.equals("->oclAsType") || "->forAll".equals(operator) || "->exists".equals(operator) || "->exists1".equals(operator) || - "->existsLC".equals(operator) || + "->existsLC".equals(operator) || "->any".equals(operator) || operator.equals("->selectMaximals") || operator.equals("->oclIsKindOf") || operator.equals("->oclIsTypeOf") || operator.equals("->includesKey") || operator.equals("->excludesKey") || operator.equals("->includesValue") || @@ -1606,6 +1648,9 @@ public boolean isPrimitive() if ("int".equals(typ) || "long".equals(typ) || "double".equals(typ) || "boolean".equals(typ)) { return true; } // or it is the name of an enum - but a strange thing to do + if (right.type != null && right.type.isEnumeration()) + // ModelElement.lookupByName(typ, types) != null) + { return true; } return false; } @@ -1635,7 +1680,15 @@ public Vector innermostVariables() } public Vector metavariables() - { Vector res = left.metavariables(); + { if ("|C".equals(operator) || "|R".equals(operator) || "|".equals(operator) || + "|A".equals(operator) || "#".equals(operator) || "#1".equals(operator) || + "!".equals(operator)) + { BinaryExpression beleft = (BinaryExpression) left; + Vector res = beleft.right.metavariables(); + res = VectorUtil.union(res,beleft.left.metavariables()); + return VectorUtil.union(res,right.metavariables()); + } + Vector res = left.metavariables(); return VectorUtil.union(res,right.metavariables()); } @@ -1645,7 +1698,7 @@ public Vector allPreTerms() if ("->forAll".equals(operator) || "->exists".equals(operator) || "->exists1".equals(operator) || "->select".equals(operator) || - "->existsLC".equals(operator) || + "->existsLC".equals(operator) || "->any".equals(operator) || "->reject".equals(operator) || "->collect".equals(operator) || "->selectMinimals".equals(operator) || "->selectMaximals".equals(operator) || "->unionAll".equals(operator) || "->intersectAll".equals(operator) || @@ -1707,7 +1760,7 @@ public Vector allPreTerms(String var) Vector rpterms = right.allPreTerms(var); if ("->forAll".equals(operator) || "->exists".equals(operator) || - "->existsLC".equals(operator) || + "->existsLC".equals(operator) || "->any".equals(operator) || "->exists1".equals(operator) || "->select".equals(operator) || "->reject".equals(operator) || "->collect".equals(operator) || "->selectMinimals".equals(operator) || "->selectMaximals".equals(operator) || @@ -1763,7 +1816,7 @@ else if ("!".equals(operator) || "#".equals(operator) || operator.equals("#LC") public Vector getBaseEntityUses() // entities E such that f occurs without an object ref { if (operator.equals("->forAll") || operator.equals("->exists") || - "->existsLC".equals(operator) || + "->existsLC".equals(operator) || operator.equals("->any") || operator.equals("->exists1") || operator.equals("->sortedBy") || operator.equals("->select") || operator.equals("->reject") || "->isUnique".equals(operator) || operator.equals("->unionAll") || @@ -1799,7 +1852,7 @@ public Vector getBaseEntityUses() // entities E such that f occurs without an o if (operator.equals("!") || operator.equals("#") || operator.equals("#LC") || operator.equals("#1") || operator.equals("|") || operator.equals("|R") || - operator.equals("|C")) + operator.equals("|A") || operator.equals("|C")) { Vector ss = right.getBaseEntityUses(); if (left instanceof BinaryExpression) { Vector res = ((BinaryExpression) left).right.getBaseEntityUses(); @@ -1815,7 +1868,7 @@ public Vector getBaseEntityUses() // entities E such that f occurs without an o } public Vector getVariableUses() - { if (operator.equals("#") || operator.equals("|") || + { if (operator.equals("#") || operator.equals("|") || operator.equals("|A") || operator.equals("|C") || operator.equals("#LC") || operator.equals("|R") || operator.equals("#1") || operator.equals("!")) { Vector ss = right.getVariableUses(); @@ -1853,6 +1906,12 @@ public Vector allFeaturesUsedIn() right.allFeaturesUsedIn()); } + public Vector allAttributesUsedIn() + { Vector res = left.allAttributesUsedIn(); + return VectorUtil.union(res, + right.allAttributesUsedIn()); + } + public Vector allOperationsUsedIn() { Vector res = left.allOperationsUsedIn(); return VectorUtil.union(res, @@ -2345,6 +2404,15 @@ public boolean typeCheck(final Vector types, final Vector entities, final Vector contexts, final Vector env) { Vector context = new Vector(); + + if (operator.equals(",")) + { left.typeCheck(types,entities,contexts,env); + right.typeCheck(types,entities,contexts,env); + type = right.type; + elementType = right.elementType; + multiplicity = right.multiplicity; + return true; + } if (operator.equals("#") || operator.equals("#1") || operator.equals("#LC") || operator.equals("!")) { BinaryExpression lexp = (BinaryExpression) left; @@ -2518,6 +2586,69 @@ else if (operator.equals("|C")) tcCollect(stleft,stright,seright); // System.out.println("TYPE OF " + this + " IS " + type + ", " + elementType); return true; + } + else if (operator.equals("->any")) + { left.typeCheck(types,entities,contexts,env); + Vector ccontext = new Vector(); + Type ctleft = left.getType(); + // must be a collection type + Type celtype = left.elementType; + if (celtype != null && celtype.isEntity()) + { ccontext.add(celtype.getEntity()); } + else if (ctleft != null && ctleft.isEntity()) + { ccontext.add(ctleft.getEntity()); } + else if (celtype == null) + { System.err.println("!!! TYPE ERROR: no element type in " + left + " in " + this); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Type error", JOptionPane.ERROR_MESSAGE); + } + + ccontext.addAll(contexts); + right.typeCheck(types,entities,ccontext,env); + type = celtype; // for ->any(Pred) + if (type != null && type.isCollectionType()) + { multiplicity = ModelElement.MANY; + elementType = type.getElementType(); + } + return true; + } + else if (operator.equals("|A")) + { BinaryExpression lexp = (BinaryExpression) left; + // must be a collection + + boolean lrt = lexp.right.typeCheck(types,entities,contexts,env); + Type et = lexp.right.elementType; + if (et == null) + { System.err.println("!! TYPE ERROR: no element type for " + lexp.right + " in " + this); JOptionPane.showMessageDialog(null, "no element type for " + lexp.right + " in " + this, "Type error", JOptionPane.ERROR_MESSAGE); + et = new Type("void", null); + } + + context.addAll(contexts); + Attribute att = + new Attribute(lexp.left + "", et, ModelElement.INTERNAL); + if (et != null) + { att.setElementType(et.getElementType()); } + + Vector env1 = new Vector(); + env1.addAll(env); + env1.add(att); + lexp.typeCheck(types,entities,contexts,env1); + boolean rtc = right.typeCheck(types,entities,context,env1); + Type stleft = lexp.right.getType(); + Type stright = right.getType(); + Entity seright = null; + if (right.elementType != null) + { if (right.elementType.isEntity()) + { seright = right.elementType.getEntity(); } + } + // tcCollect(stleft,stright,seright); + // System.out.println("TYPE OF " + this + " IS " + type + ", " + elementType); + type = et; // for ->any(x | Pred) + if (type != null && type.isCollectionType()) + { multiplicity = ModelElement.MANY; + elementType = type.getElementType(); + } + return true; } else if ("->closure".equals(operator)) { type = new Type("Set",null); @@ -2737,7 +2868,7 @@ else if (tleft == null && tright != null) } } // and set one element type to the other when not null } - else if (operator.equals("&") || operator.equals("<=>") || + else if (operator.equals("&") || operator.equals("<=>") || operator.equals("xor") || operator.equals("or") || operator.equals("=>")) { tcLogical(tleft,tright,eleft,eright); } // else, it is an extension operator, type is given by its definition @@ -2936,32 +3067,39 @@ private void tcSetOps(Type tleft, Type tright, if (tleft != null) { tlname = tleft.getName(); } else - { System.err.println("WARNING: no type for: " + left); } + { System.err.println("!! WARNING: no type for: " + left); } String trname = "Set"; if (tright != null) { trname = tright.getName(); } else - { System.err.println("WARNING: no type for: " + right); } + { System.err.println("!! WARNING: no type for: " + right); } if (left.isMultiple() || right.isMultiple()) { if (operator.equals("^") || operator.equals("->prepend") || operator.equals("->append")) { if ("Sequence".equals(tlname)) { } else - { System.err.println("WARNING: ^, prepend, append must be applied to sequence: " + this); } + { System.err.println("!! WARNING: ^, prepend, append must be applied to sequence: " + this); } type = new Type("Sequence",null); } - else if (operator.equals("->excluding") || operator.equals("->including") || - operator.equals("->intersection") || operator.equals("/\\")) + else if (operator.equals("->excluding") || + operator.equals("->including") || + operator.equals("->restrict") || + operator.equals("->intersection") || + operator.equals("/\\")) { if ("Sequence".equals(tlname)) { type = new Type("Sequence",null); } + else if ("Map".equals(tlname)) + { type = new Type("Map",null); } else { type = new Type("Set",null); } } else if (operator.equals("->union") || operator.equals("\\/")) { if (tlname.equals("Sequence") && trname.equals("Sequence")) { type = new Type("Sequence",null); } + else if (tlname.equals("Map") && trname.equals("Map")) + { type = new Type("Map",null); } else { type = new Type("Set",null); } } @@ -2973,6 +3111,8 @@ else if (tleft != null && tright != null) { type = new Type("Set",null); } else if (tleft.equals(tright) && tlname.equals("Sequence")) { type = new Type("Sequence",null); } + else if (tleft.equals(tright) && tlname.equals("Map")) + { type = new Type("Map",null); } else { System.out.println("TYPE ERROR: invalid types " + tleft + " " + tright + " in: " + this); JOptionPane.showMessageDialog(null, "Disallowed types in " + this, @@ -3003,7 +3143,9 @@ else if (tleft == null && tright != null) if (Type.isSubType(etleft,etright)) { maxtype = etright; } - if (operator.equals("->intersection") || operator.equals("/\\") || + if (operator.equals("->intersection") || + operator.equals("/\\") || + operator.equals("->restrict") || operator.equals("->excluding")) { elementType = etleft; type.setElementType(elementType); @@ -3028,7 +3170,7 @@ else if (etright != null) } private void tcSelect(Type tleft, Type tright, Entity eleft) - { // left should be set or sequence, right a boolean + { // left should be set, sequence or map, right a boolean Expression selectleft = left; @@ -3038,11 +3180,13 @@ private void tcSelect(Type tleft, Type tright, Entity eleft) } if (selectleft.isMultiple()) - { if ((tleft + "").startsWith("Sequence")) + { if (Type.isSequenceType(tleft)) { type = new Type("Sequence",null); } else if (operator.equals("->sortedBy")) { type = new Type("Sequence",null); } - else + else if (Type.isMapType(tleft)) + { type = new Type("Map", null); } + else { type = new Type("Set",null); } } else @@ -3076,7 +3220,7 @@ private void tcCollect(Type tleft, Type tright, Entity eright) if (collectleft.isMultiple()) { } else - { System.err.println("TYPE ERROR: LHS of collect must be a collection! " + this); + { System.err.println("!!! TYPE ERROR: LHS of collect must be a collection! " + this); JOptionPane.showMessageDialog(null, "LHS must be a collection: " + this, "Type error", JOptionPane.ERROR_MESSAGE); // type = null; @@ -3084,7 +3228,7 @@ private void tcCollect(Type tleft, Type tright, Entity eright) } if (tright == null) - { System.err.println("TYPE ERROR: No type for collect RHS: " + this); + { System.err.println("!!! TYPE ERROR: No type for collect RHS: " + this); JOptionPane.showMessageDialog(null, "ERROR: No type for collect RHS: " + this, "Type error", JOptionPane.ERROR_MESSAGE); return; } @@ -3092,7 +3236,9 @@ private void tcCollect(Type tleft, Type tright, Entity eright) if (operator.equals("->collect") || operator.equals("|C")) { elementType = (Type) tright.clone(); - type = new Type("Sequence",null); + type = new Type("Sequence",null); + if (Type.isMapType(tleft)) + { type = new Type("Map", null); } // map->collect(e) is the composed map. } else // ->intersectAll, ->unionAll { if (right.elementType == null) @@ -3409,6 +3555,14 @@ public String queryForm(java.util.Map env, boolean local) if (operator.equals("|C") || operator.equals("->collect")) { return collectQueryForm(lqf,rqf,rprim,env,local); } + if (operator.equals("|A") || operator.equals("->any")) + { String getany = anyQueryForm(lqf,rqf,rprim,env,local); + if (Type.isPrimitiveType(type)) + { return unwrap(getany); } + String typ = type.getJava(); + return "((" + typ + ") " + getany + ")"; + } + if (operator.equals("->selectMaximals")) { String col = collectQueryForm(lqf,rqf,rprim,env,local); if (left.umlkind == CLASSID) @@ -3433,6 +3587,9 @@ public String queryForm(java.util.Map env, boolean local) if (operator.equals("->count")) { return "Set.count(" + lqf + "," + rw + ")"; } + if (operator.equals("->restrict")) + { return "Set.restrictMap(" + lqf + "," + rw + ")"; } + if (operator.equals("->at")) { if ("String".equals(left.type + "")) { return "(" + lqf + ".charAt(" + rqf + " - 1) + \"\")"; } // and for Java6, 7, etc. @@ -3468,7 +3625,7 @@ public String queryForm(java.util.Map env, boolean local) if (operator.equals("->pow")) { return "Math.pow(" + lqf + "," + rqf + ")"; } - if (operator.equals("->isUnique")) // and define for B + if (operator.equals("->isUnique")) // and define for B and for Maps { String fcollect = collectQueryForm(lqf,rqf,rprim,env,local); return "Set.isUnique(" + fcollect + ")"; } @@ -3579,13 +3736,16 @@ else if (left instanceof SetExpression) if (operator.equals("=>")) { return "(!(" + lqf + ") || " + rqf + ")"; } + if (operator.equals("xor")) + { return "((" + lqf + " && !(" + rqf + ")) || (!(" + lqf + ") && " + rqf + "))"; } + if (operator.equals("->oclAsType")) { // Type typ = Type.getTypeFor("" + right,types,entities); if (type != null) { String jtyp = type.getJava(); return "((" + jtyp + ") " + lqf + ")"; } - return lqf; + return "((" + right + ") " + lqf + ")"; } if (extensionoperators.containsKey(operator)) @@ -3759,13 +3919,22 @@ public String queryFormJava6(java.util.Map env, boolean local) if (operator.equals("|") || operator.equals("->select")) { return selectQueryFormJava6(lqf,rqf,env,local); } - if (operator.equals("|C") || operator.equals("->collect")) // and |C + if (operator.equals("|C") || operator.equals("->collect")) { return collectQueryFormJava6(lqf,rqf,rprim,env,local); } + if (operator.equals("|A") || operator.equals("->any")) + { String getany = anyQueryFormJava6(lqf,rqf,rprim,env,local); + if (Type.isPrimitiveType(type)) + { return unwrap(getany); } + String typ = type.getJava6(); + return "((" + typ + ") " + getany + ")"; + } + if (operator.equals("->selectMaximals")) { String col = collectQueryFormJava6(lqf,rqf,rprim,env,local); if (left.umlkind == CLASSID) - { lqf = ((BasicExpression) left).classExtentQueryFormJava6(env,local); } // And pass lqf to collectQueryForm? + { lqf = ((BasicExpression) left).classExtentQueryFormJava6(env,local); } + // And pass lqf to collectQueryForm? return "Set.maximalElements(" + lqf + ", " + col + ")"; } @@ -3786,6 +3955,9 @@ public String queryFormJava6(java.util.Map env, boolean local) if (operator.equals("->count")) // not for strings { return "Collections.frequency(" + lqf + "," + rw + ")"; } + if (operator.equals("->restrict")) + { return "Set.restrictMap(" + lqf + "," + rw + ")"; } + if (operator.equals("->at") && type != null) { String getind = lqf + ".get(" + rqf + " - 1)"; if ("String".equals(left.type + "")) @@ -4033,6 +4205,14 @@ public String queryFormJava7(java.util.Map env, boolean local) if (operator.equals("|C") || operator.equals("->collect")) { return collectQueryFormJava7(lqf,rqf,rprim,env,local); } + if (operator.equals("|A") || operator.equals("->any")) + { String getany = anyQueryFormJava7(lqf,rqf,rprim,env,local); + if (Type.isPrimitiveType(type)) + { return unwrap(getany); } + String typ = type.getJava7(elementType); + return "((" + typ + ") " + getany + ")"; + } + if (operator.equals("->selectMaximals")) { String col = collectQueryFormJava7(lqf,rqf,rprim,env,local); String jType = type.getJava7(elementType); @@ -4059,6 +4239,9 @@ public String queryFormJava7(java.util.Map env, boolean local) if (operator.equals("->count") && !("String".equals(left.type + ""))) // not for strings { return "Collections.frequency(" + lqf + "," + rw + ")"; } + if (operator.equals("->restrict")) + { return "Ocl.restrictMap(" + lqf + "," + rw + ")"; } + if (operator.equals("->at") && type != null) { String getind = lqf + ".get(" + rqf + " - 1)"; if ("String".equals(left.type + "")) @@ -4331,12 +4514,21 @@ public String queryFormCSharp(java.util.Map env, boolean local) if (operator.equals("->count")) { return "SystemTypes.count(" + lqf + "," + rqf + ")"; } + if (operator.equals("->restrict")) + { return "SystemTypes.restrictMap(" + lqf + "," + rqf + ")"; } + if (operator.equals("->at") && type != null) { String typ = type.getCSharp(); if ("String".equals(left.type + "")) { return "(" + lqf + ").Substring(" + rqf + "-1 , 1)"; } return "((" + typ + ") " + lqf + "[" + rqf + " - 1])"; } + + if (operator.equals("|A") || operator.equals("->any")) + { String getany = anyQueryFormCSharp(lqf,rqf,rprim,env,local); + String typ = type.getCSharp(); + return "((" + typ + ") " + getany + ")"; + } if (operator.equals("->pow")) { return "Math.Pow(" + lqf + ", " + rqf + ")"; } @@ -4638,9 +4830,16 @@ else if (entity != null) { String typ = type.getCPP(elementType); if ("String".equals(left.type + "")) { return "(" + lqf + ").substr(" + rqf + "-1 , 1)"; } - return "((" + typ + ") " + lqf + "->at(" + rqf + " - 1))"; + return "((" + typ + ") " + lqf + "->at(" + rqf + " - 1))"; + } + + if (operator.equals("|A") || operator.equals("->any")) + { String getany = anyQueryFormCPP(lqf,rqf,env,local); + String typ = type.getCPP(elementType); + return "((" + typ + ") " + getany + ")"; } + if (operator.equals("->pow")) { return "pow(" + lqf + ", " + rqf + ")"; } @@ -5989,42 +6188,550 @@ private String rejectQueryFormJava6(String lqf, String rqf, java.util.Map env, Vector parnames = new Vector(); String callpars = ""; - // Entity localentity = left.elementType.getEntity(); + // Entity localentity = left.elementType.getEntity(); + + String selectvar = null; + Expression selectleft = left; + Entity localentity = null; + + if (operator.equals("->reject")) + { // lqf = left.queryForm(env,local); + // selectleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("|R")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormJava6(env,local); + selectleft = beleft.right; + selectvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Base entities: " + trueeuses); + // System.out.println(localentity); + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the select. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(selectvar + "") || + (selectvar == null && (use.data + "").equals("self"))) + {} + else if (selectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + String res = BSystemTypes.getRejectDefinitionJava6(selectleft,lqf,right,selectvar,env1,pars); + return "Set." + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String rejectQueryFormJava7(String lqf, String rqf, java.util.Map env, + boolean local) + { // select_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + // Entity localentity = left.elementType.getEntity(); + + String selectvar = null; + Expression selectleft = left; + Entity localentity = null; + + if (operator.equals("->reject")) + { if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("|R")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormJava7(env,local); + selectleft = beleft.right; + selectvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Base entities: " + trueeuses); + // System.out.println(localentity); + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the select. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(selectvar + "") || + (selectvar == null && (use.data + "").equals("self"))) + {} + else if (selectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + String res = BSystemTypes.getRejectDefinitionJava7(selectleft,lqf,right,selectvar,env1,pars); + return "Ocl." + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String rejectQueryFormCSharp(String lqf, String rqf, java.util.Map env, + boolean local) + { // select_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + // Entity localentity = left.elementType.getEntity(); + + String selectvar = null; + Expression selectleft = left; + Entity localentity = null; + + if (operator.equals("->reject")) + { // lqf = left.queryForm(env,local); + // selectleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("|R")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormCSharp(env,local); + selectleft = beleft.right; + selectvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Base entities: " + trueeuses); + // System.out.println(localentity); + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the select. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(selectvar + "") || + (selectvar == null && (use.data + "").equals("self"))) + {} + else if (selectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating Select " + uses + " " + env1); + String res = BSystemTypes.getRejectDefinitionCSharp(selectleft,lqf,right,selectvar,env1,pars); + return "SystemTypes." + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String rejectQueryFormCPP(String lqf, String rqf, java.util.Map env, + boolean local) + { // select_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + // Entity localentity = left.elementType.getEntity(); + + String selectvar = null; + Expression selectleft = left; + Entity localentity = null; + + if (operator.equals("->reject")) + { // lqf = left.queryForm(env,local); + // selectleft = left; + // localentity = left.getEntity(); // or entity of the elementType + if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + else if (operator.equals("|R")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryFormCPP(env,local); + selectleft = beleft.right; + selectvar = beleft.left + ""; + // localentity = beleft.right.getEntity(); // or entity of the elementType + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Base entities: " + trueeuses); + // System.out.println(localentity); + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the select. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(selectvar + "") || + (selectvar == null && (use.data + "").equals("self"))) + {} + else if (selectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + String res = BSystemTypes.getRejectDefinitionCPP(selectleft,lqf,right,selectvar,env1,pars); + return res.substring(0,res.length()-1) + callpars + ")"; + } + + + private String anyQueryForm(String lqf, String rqf, boolean rprim, + java.util.Map env, + boolean local) + { // any_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + String collectvar = null; + Expression collectleft = left; + Entity localentity = left.entity; // left.elementType.getEntity(); + + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + if (operator.equals("|A")) + { BinaryExpression beleft = (BinaryExpression) left; + lqf = beleft.right.queryForm(env,local); + collectleft = beleft.right; + collectvar = beleft.left + ""; + if (beleft.right == null || beleft.right.elementType == null) + { System.err.println("DESIGN ERROR: no element type of: " + beleft); + JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = beleft.right.elementType.getEntity(); } + } + else + { if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } + + Vector trueeuses = new Vector(); + if (localentity != null) + { trueeuses = localentity.removeMyUses(euses); } + else + { trueeuses = euses; } + + // System.out.println("Collect base entities: " + euses + " Uses: " + uses); + // System.out.println("Collect local entity: " + localentity); + + for (int j = 0; j < trueeuses.size(); j++) + { Entity externalEnt = (Entity) trueeuses.get(j); + // System.out.println("External entity used in " + this + " is: " + externalEnt); + Type etype = new Type(externalEnt); + String ename = externalEnt.getName(); + String evar = ename.toLowerCase() + "x"; + Attribute eself = new Attribute(evar,etype,ModelElement.INTERNAL); + eself.setElementType(etype); + + pars.add(eself); + parnames.add(evar); + String ex = (String) env.get(ename); + if (ex == null) + { ex = "this"; } // for outer instance context only + + callpars = callpars + "," + ex; + env1.put(ename,evar); // for evaluating the predicate of the collect. + } + + for (int i = 0; i < uses.size(); i++) + { BasicExpression use = (BasicExpression) uses.get(i); + if (parnames.contains(use.data) || (use.data + "").equals(collectvar) || + (collectvar == null && (use.data + "").equals("self"))) + {} + else if (collectvar != null && (use.data + "").equals("self") && use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + ", this"; + env1.put(use.getType().getName(), "self"); + } + else if (use.getType() != null) + { Attribute par = + new Attribute(use.data,use.getType(),ModelElement.INTERNAL); + par.setElementType(use.getElementType()); + pars.add(par); + parnames.add(use.data); + callpars = callpars + "," + use.data; + } + } + + // System.out.println("Creating Collect " + uses + " " + env1); + String res = BSystemTypes.getAnyDefinition(collectleft,lqf,right,collectvar,env1,pars); + return "Set." + res.substring(0,res.length()-1) + callpars + ")"; + } + + private String anyQueryFormJava6(String lqf, String rqf, boolean rprim, + java.util.Map env, + boolean local) + { // any_ind(lqf) where ind is a unique index for left and right + Vector uses = right.getVariableUses(); + Vector pars = new Vector(); + Vector parnames = new Vector(); + String callpars = ""; + + String collectvar = null; + Expression collectleft = left; + Entity localentity = left.entity; + // left.elementType.getEntity(); - String selectvar = null; - Expression selectleft = left; - Entity localentity = null; - - if (operator.equals("->reject")) - { // lqf = left.queryForm(env,local); - // selectleft = left; - // localentity = left.getEntity(); // or entity of the elementType - if (left.elementType == null) - { System.err.println("DESIGN ERROR: no element type for: " + left); - JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, - "Design error", JOptionPane.ERROR_MESSAGE); - } - else - { localentity = left.elementType.getEntity(); } - } - else if (operator.equals("|R")) + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + if (operator.equals("|A")) { BinaryExpression beleft = (BinaryExpression) left; lqf = beleft.right.queryFormJava6(env,local); - selectleft = beleft.right; - selectvar = beleft.left + ""; - // localentity = beleft.right.getEntity(); // or entity of the elementType + collectleft = beleft.right; + collectvar = beleft.left + ""; if (beleft.right == null || beleft.right.elementType == null) - { System.err.println("DESIGN ERROR: no element type of: " + beleft); + { System.err.println("DESIGN ERROR: no element type of: " + beleft); JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, "Design error", JOptionPane.ERROR_MESSAGE); } else { localentity = beleft.right.elementType.getEntity(); } } - - Vector euses = right.getBaseEntityUses(); - // Should only have one element, the owner of the operation in which - // this occurs. Others are localentity and its superclasses. + else + { if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } Vector trueeuses = new Vector(); if (localentity != null) @@ -6032,9 +6739,8 @@ else if (operator.equals("|R")) else { trueeuses = euses; } - // System.out.println("Base entities: " + trueeuses); - // System.out.println(localentity); - java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + // System.out.println("Collect base entities: " + euses + " Uses: " + uses); + // System.out.println("Collect local entity: " + localentity); for (int j = 0; j < trueeuses.size(); j++) { Entity externalEnt = (Entity) trueeuses.get(j); @@ -6052,15 +6758,15 @@ else if (operator.equals("|R")) { ex = "this"; } // for outer instance context only callpars = callpars + "," + ex; - env1.put(ename,evar); // for evaluating the predicate of the select. + env1.put(ename,evar); // for evaluating the predicate of the collect. } for (int i = 0; i < uses.size(); i++) { BasicExpression use = (BasicExpression) uses.get(i); - if (parnames.contains(use.data) || (use.data + "").equals(selectvar + "") || - (selectvar == null && (use.data + "").equals("self"))) + if (parnames.contains(use.data) || (use.data + "").equals(collectvar) || + (collectvar == null && (use.data + "").equals("self"))) {} - else if (selectvar != null && (use.data + "").equals("self") && use.getType() != null) + else if (collectvar != null && (use.data + "").equals("self") && use.getType() != null) { Attribute par = new Attribute(use.data,use.getType(),ModelElement.INTERNAL); par.setElementType(use.getElementType()); @@ -6079,51 +6785,54 @@ else if (use.getType() != null) } } - String res = BSystemTypes.getRejectDefinitionJava6(selectleft,lqf,right,selectvar,env1,pars); + String res = BSystemTypes.getAnyDefinitionJava6(collectleft,lqf,right,collectvar,env1,pars); return "Set." + res.substring(0,res.length()-1) + callpars + ")"; } - private String rejectQueryFormJava7(String lqf, String rqf, java.util.Map env, + private String anyQueryFormJava7(String lqf, String rqf, boolean rprim, + java.util.Map env, boolean local) - { // select_ind(lqf) where ind is a unique index for left and right + { // any_ind(lqf) where ind is a unique index for left and right Vector uses = right.getVariableUses(); Vector pars = new Vector(); Vector parnames = new Vector(); String callpars = ""; - // Entity localentity = left.elementType.getEntity(); + String collectvar = null; + Expression collectleft = left; + Entity localentity = left.entity; + // left.elementType.getEntity(); - String selectvar = null; - Expression selectleft = left; - Entity localentity = null; - - if (operator.equals("->reject")) - { if (left.elementType == null) - { System.err.println("DESIGN ERROR: no element type for: " + left); - JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, - "Design error", JOptionPane.ERROR_MESSAGE); - } - else - { localentity = left.elementType.getEntity(); } - } - else if (operator.equals("|R")) + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + if (operator.equals("|A")) { BinaryExpression beleft = (BinaryExpression) left; lqf = beleft.right.queryFormJava7(env,local); - selectleft = beleft.right; - selectvar = beleft.left + ""; - // localentity = beleft.right.getEntity(); // or entity of the elementType + collectleft = beleft.right; + collectvar = beleft.left + ""; if (beleft.right == null || beleft.right.elementType == null) - { System.err.println("DESIGN ERROR: no element type of: " + beleft); + { System.err.println("DESIGN ERROR: no element type of: " + beleft); JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, "Design error", JOptionPane.ERROR_MESSAGE); } else { localentity = beleft.right.elementType.getEntity(); } } - - Vector euses = right.getBaseEntityUses(); - // Should only have one element, the owner of the operation in which - // this occurs. Others are localentity and its superclasses. + else + { if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } Vector trueeuses = new Vector(); if (localentity != null) @@ -6131,9 +6840,8 @@ else if (operator.equals("|R")) else { trueeuses = euses; } - // System.out.println("Base entities: " + trueeuses); - // System.out.println(localentity); - java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + // System.out.println("Collect base entities: " + euses + " Uses: " + uses); + // System.out.println("Collect local entity: " + localentity); for (int j = 0; j < trueeuses.size(); j++) { Entity externalEnt = (Entity) trueeuses.get(j); @@ -6151,15 +6859,15 @@ else if (operator.equals("|R")) { ex = "this"; } // for outer instance context only callpars = callpars + "," + ex; - env1.put(ename,evar); // for evaluating the predicate of the select. + env1.put(ename,evar); // for evaluating the predicate of the collect. } for (int i = 0; i < uses.size(); i++) { BasicExpression use = (BasicExpression) uses.get(i); - if (parnames.contains(use.data) || (use.data + "").equals(selectvar + "") || - (selectvar == null && (use.data + "").equals("self"))) + if (parnames.contains(use.data) || (use.data + "").equals(collectvar) || + (collectvar == null && (use.data + "").equals("self"))) {} - else if (selectvar != null && (use.data + "").equals("self") && use.getType() != null) + else if (collectvar != null && (use.data + "").equals("self") && use.getType() != null) { Attribute par = new Attribute(use.data,use.getType(),ModelElement.INTERNAL); par.setElementType(use.getElementType()); @@ -6178,54 +6886,54 @@ else if (use.getType() != null) } } - String res = BSystemTypes.getRejectDefinitionJava7(selectleft,lqf,right,selectvar,env1,pars); + String res = BSystemTypes.getAnyDefinitionJava7(collectleft,lqf,right,collectvar,env1,pars); return "Ocl." + res.substring(0,res.length()-1) + callpars + ")"; } - private String rejectQueryFormCSharp(String lqf, String rqf, java.util.Map env, - boolean local) - { // select_ind(lqf) where ind is a unique index for left and right + private String anyQueryFormCSharp(String lqf, String rqf, boolean rprim, + java.util.Map env, + boolean local) + { // any_ind(lqf) where ind is a unique index for left and right Vector uses = right.getVariableUses(); Vector pars = new Vector(); Vector parnames = new Vector(); String callpars = ""; - // Entity localentity = left.elementType.getEntity(); + String collectvar = null; + Expression collectleft = left; + Entity localentity = left.entity; + // left.elementType.getEntity(); - String selectvar = null; - Expression selectleft = left; - Entity localentity = null; - - if (operator.equals("->reject")) - { // lqf = left.queryForm(env,local); - // selectleft = left; - // localentity = left.getEntity(); // or entity of the elementType - if (left.elementType == null) - { System.err.println("DESIGN ERROR: no element type for: " + left); - JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, - "Design error", JOptionPane.ERROR_MESSAGE); - } - else - { localentity = left.elementType.getEntity(); } - } - else if (operator.equals("|R")) + Vector euses = right.getBaseEntityUses(); + // Should only have one element, the owner of the operation in which + // this occurs. Others are localentity and its superclasses. + + + + java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + + if (operator.equals("|A")) { BinaryExpression beleft = (BinaryExpression) left; lqf = beleft.right.queryFormCSharp(env,local); - selectleft = beleft.right; - selectvar = beleft.left + ""; - // localentity = beleft.right.getEntity(); // or entity of the elementType + collectleft = beleft.right; + collectvar = beleft.left + ""; if (beleft.right == null || beleft.right.elementType == null) - { System.err.println("DESIGN ERROR: no element type of: " + beleft); + { System.err.println("DESIGN ERROR: no element type of: " + beleft); JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, "Design error", JOptionPane.ERROR_MESSAGE); } else { localentity = beleft.right.elementType.getEntity(); } } - - Vector euses = right.getBaseEntityUses(); - // Should only have one element, the owner of the operation in which - // this occurs. Others are localentity and its superclasses. + else + { if (left.elementType == null) + { System.err.println("DESIGN ERROR: no element type for: " + left); + JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, + "Design error", JOptionPane.ERROR_MESSAGE); + } + else + { localentity = left.elementType.getEntity(); } + } Vector trueeuses = new Vector(); if (localentity != null) @@ -6233,9 +6941,8 @@ else if (operator.equals("|R")) else { trueeuses = euses; } - // System.out.println("Base entities: " + trueeuses); - // System.out.println(localentity); - java.util.Map env1 = (java.util.Map) ((java.util.HashMap) env).clone(); + // System.out.println("Collect base entities: " + euses + " Uses: " + uses); + // System.out.println("Collect local entity: " + localentity); for (int j = 0; j < trueeuses.size(); j++) { Entity externalEnt = (Entity) trueeuses.get(j); @@ -6253,15 +6960,15 @@ else if (operator.equals("|R")) { ex = "this"; } // for outer instance context only callpars = callpars + "," + ex; - env1.put(ename,evar); // for evaluating the predicate of the select. + env1.put(ename,evar); // for evaluating the predicate of the collect. } for (int i = 0; i < uses.size(); i++) { BasicExpression use = (BasicExpression) uses.get(i); - if (parnames.contains(use.data) || (use.data + "").equals(selectvar + "") || - (selectvar == null && (use.data + "").equals("self"))) + if (parnames.contains(use.data) || (use.data + "").equals(collectvar) || + (collectvar == null && (use.data + "").equals("self"))) {} - else if (selectvar != null && (use.data + "").equals("self") && use.getType() != null) + else if (collectvar != null && (use.data + "").equals("self") && use.getType() != null) { Attribute par = new Attribute(use.data,use.getType(),ModelElement.INTERNAL); par.setElementType(use.getElementType()); @@ -6280,30 +6987,24 @@ else if (use.getType() != null) } } - // System.out.println("Creating Select " + uses + " " + env1); - String res = BSystemTypes.getRejectDefinitionCSharp(selectleft,lqf,right,selectvar,env1,pars); + String res = BSystemTypes.getAnyDefinitionCSharp(collectleft,lqf,right,collectvar,env1,pars); return "SystemTypes." + res.substring(0,res.length()-1) + callpars + ")"; } - - private String rejectQueryFormCPP(String lqf, String rqf, java.util.Map env, - boolean local) + + private String anyQueryFormCPP(String lqf, String rqf, java.util.Map env, + boolean local) { // select_ind(lqf) where ind is a unique index for left and right Vector uses = right.getVariableUses(); Vector pars = new Vector(); Vector parnames = new Vector(); String callpars = ""; - // Entity localentity = left.elementType.getEntity(); - + Entity localentity = entity; // left.elementType.getEntity(); String selectvar = null; Expression selectleft = left; - Entity localentity = null; - - if (operator.equals("->reject")) - { // lqf = left.queryForm(env,local); - // selectleft = left; - // localentity = left.getEntity(); // or entity of the elementType - if (left.elementType == null) + + if (operator.equals("->any")) + { if (left.elementType == null) { System.err.println("DESIGN ERROR: no element type for: " + left); JOptionPane.showMessageDialog(null, "no element type for " + left + " in " + this, "Design error", JOptionPane.ERROR_MESSAGE); @@ -6311,14 +7012,13 @@ private String rejectQueryFormCPP(String lqf, String rqf, java.util.Map env, else { localentity = left.elementType.getEntity(); } } - else if (operator.equals("|R")) + else if (operator.equals("|A")) { BinaryExpression beleft = (BinaryExpression) left; lqf = beleft.right.queryFormCPP(env,local); selectleft = beleft.right; selectvar = beleft.left + ""; - // localentity = beleft.right.getEntity(); // or entity of the elementType if (beleft.right == null || beleft.right.elementType == null) - { System.err.println("DESIGN ERROR: no element type of: " + beleft); + { System.out.println("DESIGN ERROR: no element type of: " + beleft); JOptionPane.showMessageDialog(null, "no element type for " + beleft + " in " + this, "Design error", JOptionPane.ERROR_MESSAGE); } @@ -6326,6 +7026,7 @@ else if (operator.equals("|R")) { localentity = beleft.right.elementType.getEntity(); } } + Vector euses = right.getBaseEntityUses(); // Should only have one element, the owner of the operation in which // this occurs. Others are localentity and its superclasses. @@ -6361,7 +7062,7 @@ else if (operator.equals("|R")) for (int i = 0; i < uses.size(); i++) { BasicExpression use = (BasicExpression) uses.get(i); - if (parnames.contains(use.data) || (use.data + "").equals(selectvar + "") || + if (parnames.contains(use.data) || (use.data + "").equals(selectvar) || (selectvar == null && (use.data + "").equals("self"))) {} else if (selectvar != null && (use.data + "").equals("self") && use.getType() != null) @@ -6371,7 +7072,7 @@ else if (selectvar != null && (use.data + "").equals("self") && use.getType() != pars.add(par); parnames.add(use.data); callpars = callpars + ", this"; - env1.put(use.getType().getName(), "self"); + env1.put(use.getType().getName(), "self"); } else if (use.getType() != null) { Attribute par = @@ -6383,8 +7084,10 @@ else if (use.getType() != null) } } - String res = BSystemTypes.getRejectDefinitionCPP(selectleft,lqf,right,selectvar,env1,pars); - return res.substring(0,res.length()-1) + callpars + ")"; + // System.out.println("Creating Select " + uses + " " + env1); + String res = BSystemTypes.getAnyDefinitionCPP(selectleft,lqf,right,selectvar,env1,pars); + return // "UmlRsdsLib<" + localentity.getName() + "*>::" + + res.substring(0,res.length()-1) + callpars + ")"; } @@ -6680,7 +7383,7 @@ else if (use.getType() != null) } // System.out.println(">>>>> Creating Collect " + right + " " + right.getType()); - String res = BSystemTypes.getCollectDefinitionJava7(collectleft,lqf,right,rprim,collectvar,env1,pars); + String res = BSystemTypes.getCollectDefinitionJava7(collectleft,lqf,right,rprim,collectvar,env1,pars); return "Ocl." + res.substring(0,res.length()-1) + callpars + ")"; } @@ -8042,15 +8745,25 @@ else if (operator.equals("/=") || operator.equals("!=")) else if (operator.equals(":") || operator.equals("<:")) { res = rqf + ".containsAll(" + lqf + ")"; } else if (operator.equals("->includesAll")) - { res = lqf + ".containsAll(" + rqf + ")"; } + { if (left.isMap() && right.isMap()) + { res = "Set.includesAllMap(" + lqf + "," + rqf + ")"; } + else + { res = lqf + ".containsAll(" + rqf + ")"; } + } else if (operator.equals("-")) - { res = "Set.subtract(" + lqf + "," + rqf + ")"; } + { if (left.isMap() && right.isMap()) + { res = "Set.excludeAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "Set.subtract(" + lqf + "," + rqf + ")"; } + } else if (operator.equals("->excluding")) { res = "Set.subtract(" + lqf + "," + rqf + ")"; } else if (operator.equals("\\/") || operator.equals("->union")) - { if (left.isOrdered() && right.isOrdered()) + { if (left.isMap() && right.isMap()) + { res = "Set.unionMap(" + lqf + "," + rqf + ")"; } + else if (left.isOrdered() && right.isOrdered()) { res = "Set.concatenate(" + lqf + ", " + rqf + ")"; } - else + else { res = "Set.union(" + lqf + "," + rqf + ")"; } } else if (operator.equals("->including")) @@ -8060,11 +8773,19 @@ else if (operator.equals("->including")) { res = "Set.union(" + lqf + "," + rqf + ")"; } } else if (operator.equals("/\\") || operator.equals("->intersection")) - { res = "Set.intersection(" + lqf + "," + rqf + ")"; } + { if (left.isMap() && right.isMap()) + { res = "Set.intersectionMap(" + lqf + "," + rqf + ")"; } + else + { res = "Set.intersection(" + lqf + "," + rqf + ")"; } + } else if (operator.equals("/:") || operator.equals("/<:")) { res = "!(" + rqf + ".containsAll(" + lqf + "))"; } else if (operator.equals("->excludesAll")) - { res = "(Set.intersection(" + rqf + "," + lqf + ").size() == 0)"; } + { if (left.isMap() && right.isMap()) + { res = "Set.excludesAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "(Set.intersection(" + rqf + "," + lqf + ").size() == 0)"; } + } else if (operator.equals("^")) { res = "Set.concatenate(" + lqf + "," + rqf + ")"; } else if (operator.equals("->symmetricDifference")) @@ -8085,13 +8806,23 @@ else if (operator.equals("/=") || operator.equals("!=")) else if (operator.equals(":") || operator.equals("<:")) { res = rqf + ".containsAll(" + lqf + ")"; } else if (operator.equals("->includesAll")) - { res = lqf + ".containsAll(" + rqf + ")"; } + { if (left.isMap() && right.isMap()) + { res = "Set.includesAllMap(" + lqf + "," + rqf + ")"; } + else + { res = lqf + ".containsAll(" + rqf + ")"; } + } else if (operator.equals("-")) - { res = "Set.subtract(" + lqf + "," + rqf + ")"; } + { if (left.isMap() && right.isMap()) + { res = "Set.excludeAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "Set.subtract(" + lqf + "," + rqf + ")"; } + } else if (operator.equals("->excluding")) { res = "Set.subtract(" + lqf + "," + rqf + ")"; } else if (operator.equals("\\/") || operator.equals("->union")) - { if (left.isOrdered() && right.isOrdered()) + { if (left.isMap() && right.isMap()) + { res = "Set.unionMap(" + lqf + "," + rqf + ")"; } + else if (left.isOrdered() && right.isOrdered()) { res = "Set.concatenate(" + lqf + ", " + rqf + ")"; } else { res = "Set.union(" + lqf + "," + rqf + ")"; } @@ -8103,11 +8834,19 @@ else if (operator.equals("->including")) { res = "Set.union(" + lqf + "," + rqf + ")"; } } else if (operator.equals("/\\") || operator.equals("->intersection")) - { res = "Set.intersection(" + lqf + "," + rqf + ")"; } + { if (left.isMap() && right.isMap()) + { res = "Set.intersectionMap(" + lqf + "," + rqf + ")"; } + else + { res = "Set.intersection(" + lqf + "," + rqf + ")"; } + } else if (operator.equals("/:") || operator.equals("/<:")) { res = "!(" + rqf + ".containsAll(" + lqf + "))"; } else if (operator.equals("->excludesAll")) - { res = "Collections.disjoint(" + lqf + "," + rqf + ")"; } + { if (left.isMap() && right.isMap()) + { res = "Set.excludesAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "Collections.disjoint(" + lqf + "," + rqf + ")"; } + } else if (operator.equals("^")) { res = "Set.concatenate(" + lqf + "," + rqf + ")"; } else if (operator.equals("->symmetricDifference")) @@ -8128,13 +8867,23 @@ else if (operator.equals("/=") || operator.equals("!=")) else if (operator.equals(":") || operator.equals("<:")) { res = rqf + ".containsAll(" + lqf + ")"; } else if (operator.equals("->includesAll")) - { res = lqf + ".containsAll(" + rqf + ")"; } + { if (left.isMap() && right.isMap()) + { res = "Ocl.includesAllMap(" + lqf + "," + rqf + ")"; } + else + { res = lqf + ".containsAll(" + rqf + ")"; } + } else if (operator.equals("-")) - { res = "Ocl.subtract(" + lqf + "," + rqf + ")"; } + { if (left.isMap() && right.isMap()) + { res = "Ocl.excludeAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "Ocl.subtract(" + lqf + "," + rqf + ")"; } + } else if (operator.equals("->excluding")) { res = "Ocl.subtract(" + lqf + "," + rqf + ")"; } else if (operator.equals("\\/") || operator.equals("->union")) - { if (left.isOrdered() && right.isOrdered()) + { if (left.isMap() && right.isMap()) + { res = "Ocl.unionMap(" + lqf + "," + rqf + ")"; } + else if (left.isOrdered() && right.isOrdered()) { res = "Ocl.concatenate(" + lqf + ", " + rqf + ")"; } else { res = "Ocl.union(" + lqf + "," + rqf + ")"; } @@ -8146,11 +8895,19 @@ else if (operator.equals("->including")) { res = "Ocl.union(" + lqf + "," + rqf + ")"; } } else if (operator.equals("/\\") || operator.equals("->intersection")) - { res = "Ocl.intersection(" + lqf + "," + rqf + ")"; } + { if (left.isMap() && right.isMap()) + { res = "Ocl.intersectionMap(" + lqf + "," + rqf + ")"; } + else + { res = "Ocl.intersection(" + lqf + "," + rqf + ")"; } + } else if (operator.equals("/:") || operator.equals("/<:")) { res = "!(" + rqf + ".containsAll(" + lqf + "))"; } else if (operator.equals("->excludesAll")) - { res = "Collections.disjoint(" + lqf + "," + rqf + ")"; } + { if (left.isMap() && right.isMap()) + { res = "Ocl.excludesAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "Collections.disjoint(" + lqf + "," + rqf + ")"; } + } else if (operator.equals("^")) { res = "Ocl.concatenate(" + lqf + "," + rqf + ")"; } else if (operator.equals("->symmetricDifference")) @@ -8180,13 +8937,23 @@ else if (operator.equals("/=") || operator.equals("!=")) else if (operator.equals(":") || operator.equals("<:")) { res = "SystemTypes.isSubset(" + lqf + "," + rqf + ")"; } else if (operator.equals("->includesAll")) - { res = "SystemTypes.isSubset(" + rqf + "," + lqf + ")"; } + { if (left.isMap() && right.isMap()) + { res = "SystemTypes.includesAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "SystemTypes.isSubset(" + rqf + "," + lqf + ")"; } + } else if (operator.equals("-")) - { res = "SystemTypes.subtract(" + lqf + "," + rqf + ")"; } + { if (left.isMap() && right.isMap()) + { res = "SystemTypes.excludeAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "SystemTypes.subtract(" + lqf + "," + rqf + ")"; } + } else if (operator.equals("->excluding")) { res = "SystemTypes.subtract(" + lqf + "," + rqf + ")"; } else if (operator.equals("\\/") || operator.equals("->union")) - { if (left.isOrdered() && right.isOrdered()) + { if (left.isMap() && right.isMap()) + { res = "SystemTypes.unionMap(" + lqf + "," + rqf + ")"; } + else if (left.isOrdered() && right.isOrdered()) { res = "SystemTypes.concatenate(" + lqf + ", " + rqf + ")"; } else { res = "SystemTypes.union(" + lqf + "," + rqf + ")"; } @@ -8198,11 +8965,19 @@ else if (operator.equals("->including")) { res = "SystemTypes.union(" + lqf + "," + rqf + ")"; } } else if (operator.equals("/\\") || operator.equals("->intersection")) - { res = "SystemTypes.intersection(" + lqf + "," + rqf + ")"; } + { if (left.isMap() && right.isMap()) + { res = "SystemTypes.intersectionMap(" + lqf + "," + rqf + ")"; } + else + { res = "SystemTypes.intersection(" + lqf + "," + rqf + ")"; } + } else if (operator.equals("/:") || operator.equals("/<:")) { res = "!(SystemTypes.isSubset(" + lqf + ", " + rqf + "))"; } else if (operator.equals("->excludesAll")) - { res = "(SystemTypes.intersection(" + rqf + "," + lqf + ").Count == 0)"; } + { if (left.isMap() && right.isMap()) + { res = "SystemTypes.excludesAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "(SystemTypes.intersection(" + rqf + "," + lqf + ").Count == 0)"; } + } else if (operator.equals("^")) { res = "SystemTypes.concatenate(" + lqf + "," + rqf + ")"; } else if (operator.equals("->symmetricDifference")) @@ -8231,9 +9006,17 @@ else if (operator.equals("/=") || operator.equals("!=")) else if (operator.equals(":") || operator.equals("<:")) { res = "UmlRsdsLib<" + lcet + ">::isSubset(" + lqf + ", " + rqf + ")"; } else if (operator.equals("->includesAll")) - { res = "UmlRsdsLib<" + lcet + ">::isSubset(" + rqf + ", " + lqf + ")"; } + { if (left.isMap() && right.isMap()) + { res = "UmlRsdsLib<" + lcet + ">::includesAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "UmlRsdsLib<" + lcet + ">::isSubset(" + rqf + ", " + lqf + ")"; } + } else if (operator.equals("-")) - { res = "UmlRsdsLib<" + lcet + ">::subtract(" + lqf + ", " + rqf + ")"; } + { if (left.isMap() && right.isMap()) + { res = "UmlRsdsLib<" + lcet + ">::excludeAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "UmlRsdsLib<" + lcet + ">::subtract(" + lqf + ", " + rqf + ")"; } + } else if (operator.equals("->excluding")) { // String rss = makeSetCPP(rqf); res = "UmlRsdsLib<" + lcet + ">::subtract(" + lqf + ", " + rqf + ")"; @@ -8246,17 +9029,27 @@ else if (operator.equals("->including")) { res = "UmlRsdsLib<" + lcet + ">::unionSet(" + lqf + ", " + rqf + ")"; } } else if (operator.equals("\\/") || operator.equals("->union")) - { if (left.isOrdered() && right.isOrdered()) + { if (left.isMap() && right.isMap()) + { res = "UmlRsdsLib<" + lcet + ">::unionMap(" + lqf + "," + rqf + ")"; } + else if (left.isOrdered() && right.isOrdered()) { res = "UmlRsdsLib<" + lcet + ">::concatenate(" + lqf + ", " + rqf + ")"; } else // BOTH sets { res = "UmlRsdsLib<" + lcet + ">::unionSet(" + lqf + ", " + rqf + ")"; } } else if (operator.equals("/\\") || operator.equals("->intersection")) - { res = "UmlRsdsLib<" + lcet + ">::intersection(" + lqf + ", " + rqf + ")"; } + { if (left.isMap() && right.isMap()) + { res = "UmlRsdsLib<" + lcet + ">::intersectionMap(" + lqf + "," + rqf + ")"; } + else + { res = "UmlRsdsLib<" + lcet + ">::intersection(" + lqf + ", " + rqf + ")"; } + } else if (operator.equals("/:") || operator.equals("/<:")) { res = "!(UmlRsdsLib<" + lcet + ">::isSubset(" + lqf + ", " + rqf + "))"; } else if (operator.equals("->excludesAll")) - { res = "(UmlRsdsLib<" + lcet + ">::intersection(" + rqf + ", " + lqf + ")->size() == 0)"; } + { if (left.isMap() && right.isMap()) + { res = "UmlRsdsLib<" + lcet + ">::excludesAllMap(" + lqf + "," + rqf + ")"; } + else + { res = "(UmlRsdsLib<" + lcet + ">::intersection(" + rqf + ", " + lqf + ")->size() == 0)"; } + } else if (operator.equals("^")) { res = "UmlRsdsLib<" + lcet + ">::concatenate(" + lqf + ", " + rqf + ")"; } else if (operator.equals("->symmetricDifference")) @@ -8381,6 +9174,29 @@ else if (eleft != null && Type.isPrimitiveType(eleft)) return ufl + "\n " + ufr; } + if (operator.equals("or")) + { String ufl = left.updateForm(env,local); + String qfl = left.queryForm(env,local); + String ufr = right.updateForm(env,local); + return ufl + "\n if (" + qfl + ") {}\n else\n { " + ufr + " }"; + } + + if (operator.equals("xor")) + { Expression notleft = negate(left); + Expression notright = negate(right); + Statement stat1 = left.statLC(env,local); + Statement stat2 = notright.statLC(env,local); + String ufl = stat1.updateForm(env,local,new Vector(), new Vector(), new Vector()) + + "\n " + stat2.updateForm(env,local,new Vector(), new Vector(), new Vector()); + + String qfl1 = left.queryForm(env,local); + String qfl2 = notright.queryForm(env,local); + String ufr1 = right.updateForm(env,local); + String ufr2 = notleft.updateForm(env,local); + return ufl + "\n if (" + qfl1 + " && " + qfl2 + ") {}\n else\n { " + ufr1 + + "\n " + ufr2 + " }"; + } + if (operator.equals("=>")) { String ufl = left.queryForm(env,local); String ufr = right.updateForm(env,local); @@ -8475,7 +9291,7 @@ else if ((operator.equals("->includes") || { return bel.updateForm(env,"/:",val3,right,local); } } else - { return "{} /* No update form for: " + this + " */"; + { return "{} // No update form for: " + this + "\n"; } } @@ -8547,7 +9363,7 @@ else if ("->including".equals(operator)) return " if (" + test.queryForm(language, env, local) + ") { }\n" + " else { " + adda.updateForm(language, env, local) + " }"; } - return "/* No update form for " + var + " : " + this + " */"; + return "{ } // No update form for " + var + " : " + this + " \n"; } public String updateFormNotIn(String language, java.util.Map env, Expression var, boolean local) @@ -8812,13 +9628,24 @@ public String updateFormExistsLCCPP(java.util.Map env, boolean local) public Statement statLC(java.util.Map env, boolean local) { String val2; - if (operator.equals("#") || operator.equals("#1") || operator.equals("#LC")) + + if (operator.equals("#") || operator.equals("#1")) + { return generateDesignExists(env,local); } + + if (operator.equals("#LC")) { return statLCExists(env,local); } if (operator.equals("or")) { SequenceStatement skip = new SequenceStatement(); if (left.isExecutable()) { Statement leftdesign = left.statLC(env,local); + if (right.isExecutable()) + { Statement rightdesign = right.statLC(env,local); + SequenceStatement res = new SequenceStatement(); + res.addStatement(leftdesign); + res.addStatement(new ConditionalStatement(this, skip, rightdesign)); + return res; + } return new ConditionalStatement(this, skip, leftdesign); } else @@ -8850,7 +9677,7 @@ public Statement statLC(java.util.Map env, boolean local) { Statement ufr = right.statLC(env,local); if ("true".equals(left + "")) { return ufr; } - IfStatement istat = new IfStatement(left,ufr); + ConditionalStatement istat = new ConditionalStatement(left,ufr); return istat; } @@ -8864,7 +9691,7 @@ public Statement statLC(java.util.Map env, boolean local) if (lbe.isOrdered()) { Statement skip = new SequenceStatement(); upd.setBrackets(true); - return new IfStatement(this, skip, upd); + return new ConditionalStatement(this, skip, upd); } return upd; } // but ->forAll in fact @@ -8872,14 +9699,14 @@ else if (operator.equals("->excludesAll")) { Statement upd = lbe.generateDesignSubtract(right); Statement skip = new SequenceStatement(); upd.setBrackets(true); - return new IfStatement(this, skip, upd); + return new ConditionalStatement(this, skip, upd); } else if (operator.equals("->includes")) { Statement upd = lbe.generateDesignIn(right); if (lbe.isOrdered()) { Statement skip = new SequenceStatement(); upd.setBrackets(true); - return new IfStatement(this, skip, upd); + return new ConditionalStatement(this, skip, upd); } return upd; } @@ -8887,7 +9714,7 @@ else if (operator.equals("->excludes")) { Statement upd = lbe.generateDesignNotIn(right); Statement skip = new SequenceStatement(); upd.setBrackets(true); - return new IfStatement(this, skip, upd); + return new ConditionalStatement(this, skip, upd); } } @@ -8901,7 +9728,7 @@ else if (operator.equals("->excludes")) if (rbe.isOrdered()) { Statement skip = new SequenceStatement(); upd.setBrackets(true); - return new IfStatement(test, skip, upd); + return new ConditionalStatement(test, skip, upd); } return upd; } // but ->forAll in fact @@ -8912,7 +9739,7 @@ else if (operator.equals("/<:")) test.setType(type); test.setElementType(elementType); upd.setBrackets(true); - return new IfStatement(test, skip, upd); + return new ConditionalStatement(test, skip, upd); } else if (operator.equals(":")) { Statement upd = rbe.generateDesignIn(left); @@ -8923,7 +9750,7 @@ else if (operator.equals(":")) if (rbe.isOrdered()) { Statement skip = new SequenceStatement(); upd.setBrackets(true); - return new IfStatement(test, skip, upd); + return new ConditionalStatement(test, skip, upd); } return upd; } @@ -8934,7 +9761,7 @@ else if (operator.equals("/:")) test.setElementType(elementType); Statement skip = new SequenceStatement(); upd.setBrackets(true); - return new IfStatement(test, skip, upd); + return new ConditionalStatement(test, skip, upd); } } @@ -8963,6 +9790,9 @@ public Statement statLCExists(java.util.Map env, boolean local) // is var evar : ltype; stat(right) Vector preds = right.getConjuncts(); + + System.out.println(">->-> Conjuncts of " + right + " are: " + preds); + String ename = ent.getName(); Expression eset = new BasicExpression(ename.toLowerCase() + "$set"); eset.umlkind = VARIABLE; @@ -9189,11 +10019,24 @@ public Statement generateDesign(java.util.Map env, boolean local) return sstat; } + if (operator.equals("or")) + { Statement ufl = left.generateDesign(env,local); + Statement ufr = right.generateDesign(env,local); + SequenceStatement sstat = new SequenceStatement(); + sstat.addStatement(ufl); + SequenceStatement skip = new SequenceStatement(); + ConditionalStatement cs = new ConditionalStatement(left,skip,ufr); + sstat.addStatement(cs); + return sstat; + } + + // And for xor + if (operator.equals("=>")) { Statement ufr = right.generateDesign(env,local); if ("true".equals("" + left)) { return ufr; } - IfStatement istat = new IfStatement(left, ufr); + ConditionalStatement istat = new ConditionalStatement(left, ufr); return istat; } // accumulate the cases @@ -9232,7 +10075,7 @@ else if (operator.equals("->excludes") && left instanceof BasicExpression) return lbe.generateDesignNotIn(right); } - return new InvocationStatement("/* No update form for: " + this + " */"); + return new ImplicitInvocationStatement(this); } public String updateFormEq(String language, java.util.Map env, String op, @@ -10076,22 +10919,24 @@ public Statement generateDesignExists(java.util.Map env, boolean local) { // lvar : T := createT() ; where T is type of ltype // ufr BasicExpression invokecreent1; - if ((ltype + "").startsWith("Set")) + if ((ltype + "").startsWith("Set(")) { invokecreent1 = new BasicExpression("createSet"); + invokecreent1.setParameters(new Vector()); // I'm sure this is correct invokecreent1.type = new Type("Set", null); } - else if ((ltype + "").startsWith("Sequence")) + else if ((ltype + "").startsWith("Sequence(")) { invokecreent1 = new BasicExpression("createSequence"); + invokecreent1.setParameters(new Vector()); // I'm sure this is correct invokecreent1.type = new Type("Sequence", null); } else { invokecreent1 = new BasicExpression("create" + ent); + invokecreent1.setParameters(new Vector()); // I'm sure this is correct invokecreent1.type = new Type(ent); } invokecreent1.umlkind = UPDATEOP; // invokecreent.entity = ent; - ; invokecreent1.elementType = new Type(ent); // and Controller as an objectRef AssignStatement assgn1 = new AssignStatement(lvar, invokecreent1); @@ -10147,6 +10992,7 @@ else if ((ltype + "").startsWith("Sequence")) // invokecreent.entity = ent; invokecreent2.type = new Type(ent); invokecreent2.elementType = new Type(ent); + invokecreent2.setParameters(new Vector()); // I'm sure this is correct // and Controller as an objectRef AssignStatement assgn2 = new AssignStatement(lvar, invokecreent2); assgn2.setType(ltype.elementType); @@ -10168,6 +11014,7 @@ else if ((ltype + "").startsWith("Sequence")) BasicExpression invokecreent3 = new BasicExpression("create" + ent); invokecreent3.umlkind = UPDATEOP; // invokecreent.entity = ent; + invokecreent3.setParameters(new Vector()); // I'm sure this is correct invokecreent3.type = new Type(ent); invokecreent3.elementType = new Type(ent); // and Controller as an objectRef @@ -12197,7 +13044,7 @@ public Expression simplify() public Expression substitute(final Expression oldE, final Expression newE) - { if (operator.equals("#") || operator.equals("#1") || operator.equals("!") || + { if (operator.equals("#") || operator.equals("#1") || operator.equals("!") || operator.equals("|A") || operator.equals("#LC") || operator.equals("|") || operator.equals("|C") || operator.equals("|R")) { Expression var = ((BinaryExpression) left).left; Vector vars = oldE.getVariableUses(); @@ -13212,16 +14059,26 @@ public DataDependency getDataItems() public DataDependency rhsDataDependency() { // if p.f = val then val, p --> f - if (operator.equals("=")) + if (operator.equals("&")) + { DataDependency dd1 = left.rhsDataDependency(); + DataDependency dd2 = right.rhsDataDependency(); + dd1.union(dd2); + return dd1; + } + else if (operator.equals("#")) + { DataDependency dd2 = right.rhsDataDependency(); + return dd2; + } + else if (operator.equals("=")) { if (left instanceof BasicExpression) { BasicExpression bel = (BasicExpression) left; DataDependency dr = right.getDataItems(); - if (bel.objectRef != null || bel.arrayIndex != null) - { DataDependency pr = bel.getDataItems(); - dr.union(pr); - } + // if (bel.objectRef != null || bel.arrayIndex != null) + // { DataDependency pr = bel.getDataItems(); + // dr.union(pr); + // } dr.addTarget(new BasicExpression(bel.data)); - System.out.println("Data dependency: " + this + " is: " + dr); + System.out.println(">>> Data dependency: " + this + " is: " + dr); return dr; } else if (right instanceof BasicExpression) @@ -13651,7 +14508,7 @@ public Vector writeFrame() } return res; } - if (operator.equals("&")) + if (operator.equals("&") || operator.equals("xor")) { res = left.writeFrame(); res.addAll(right.writeFrame()); return res; @@ -13701,7 +14558,7 @@ public Vector wr(Vector assocs) if (operator.equals(":") || operator.equals("<:") || operator.equals("/:") || operator.equals("/<:")) { return right.wr(assocs); } - if (operator.equals("&")) + if (operator.equals("&") || operator.equals("xor")) { return VectorUtil.union(left.wr(assocs),right.wr(assocs)); } if (operator.equals("#") || operator.equals("#LC") || operator.equals("#1")) { // left is not written if it is preform, abstract class or not a class @@ -13742,7 +14599,7 @@ public Vector cwr(Vector assocs) operator.equals("/:") || operator.equals("/<:")) { return res; } - if (operator.equals("&")) + if (operator.equals("&") || operator.equals("xor")) { return VectorUtil.union(left.cwr(assocs),right.cwr(assocs)); } if (operator.equals("#") || operator.equals("#LC") || operator.equals("#1")) @@ -14560,12 +15417,48 @@ else if (right instanceof BinaryExpression) public String cg(CGSpec cgs) { String etext = this + ""; + if (needsBracket) + { etext = "(" + etext + ")"; } + Vector args = new Vector(); - args.add(left.cg(cgs)); - args.add(right.cg(cgs)); + if ("|C".equals(operator) || "|R".equals(operator) || + "|".equals(operator) || "#".equals(operator) || + "#1".equals(operator) || + "!".equals(operator) || "|A".equals(operator)) + { BinaryExpression beleft = (BinaryExpression) getLeft(); + args.add(beleft.getRight().cg(cgs)); + args.add(beleft.getLeft().cg(cgs)); + args.add(right.cg(cgs)); + } + else if ("->collect".equals(operator) || "->reject".equals(operator) || + "->select".equals(operator) || "->exists".equals(operator) || + "->exists1".equals(operator) || "->forAll".equals(operator) || + "->isUnique".equals(operator) || "->sortedBy".equals(operator) || + "->any".equals(operator)) + { String id = Identifier.nextIdentifier("var"); + args.add(left.cg(cgs)); + BasicExpression v = new BasicExpression(id); + v.setType(left.getElementType()); + args.add(v.cg(cgs)); + Expression newright = right.addReference(v,left.getElementType()); + newright.setType(right.getType()); + newright.setElementType(right.getElementType()); + args.add(newright.cg(cgs)); + } + else + { args.add(left.cg(cgs)); + args.add(right.cg(cgs)); + } + CGRule r = cgs.matchedBinaryExpressionRule(this,etext); if (r != null) - { return r.applyRule(args); } + { System.out.println(">> Found rule " + r + " for: " + etext); + String res = r.applyRule(args); + if (needsBracket) + { return "(" + res + ")"; } + else + { return res; } + } return etext; } diff --git a/Binding.java b/Binding.java index 776cf3f9..b6bbafc9 100644 --- a/Binding.java +++ b/Binding.java @@ -21,9 +21,15 @@ public Binding(String att, Expression exp) expression = exp; } + public String getPropertyName() + { return propertyName; } + public String toString() { return propertyName + " <- " + expression; } + public Statement toStatement() + { return new AssignStatement(propertyName,expression); } + public Expression toExpression(String nme, Type typ, Vector types, Vector ents, Vector env, java.util.Map interp, UseCase uc) { // nme.propertyName = expression, with conversions of thisModule @@ -82,4 +88,9 @@ public Vector operationsUsedIn() public Vector getUses(String data) { return expression.getUses(data); } + + public Binding substitute(String v, Expression expr) + { Expression newexpr = expression.substituteEq(v,expr); + return new Binding(propertyName,newexpr); + } } \ No newline at end of file diff --git a/CGCondition.java b/CGCondition.java new file mode 100644 index 00000000..1528ae1b --- /dev/null +++ b/CGCondition.java @@ -0,0 +1,204 @@ +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ +/* Package: Code Generation */ + +import java.util.Vector; + +public class CGCondition +{ String stereotype = ""; + String variable = ""; + boolean positive = true; + + public CGCondition() + { } + + public CGCondition(String prop, String var) + { stereotype = prop; + variable = var; + } + + public void setVariable(String v) + { variable = v; } + + public void setStereotype(String st) + { stereotype = st; } + + public void setPositive() + { positive = true; } + + public void setNegative() + { positive = false; } + + public String toString() + { String res = variable; + if (positive) { } + else + { res = res + " not"; } + return res + " " + stereotype; + } + + public static boolean conditionsSatisfied(Vector conditions, Vector args) + { boolean res = true; + for (int i = 0; i < args.size(); i++) + { Object m = args.get(i); + String var = "_" + (i+1); + + for (int j = 0; j < conditions.size(); j++) + { CGCondition cond = (CGCondition) conditions.get(j); + if (cond.variable != null && var.equals(cond.variable)) + { if (m instanceof Type && + cond.conditionSatisfied((Type) m)) + { } + else if (m instanceof Expression && + cond.conditionSatisfied((Expression) m)) + { } + else if (m instanceof Statement && + cond.conditionSatisfied((Statement) m)) + { } + else if (m instanceof Attribute && + cond.conditionSatisfied((Attribute) m)) + { } + else if (m instanceof ModelElement && + cond.stereotypeConditionSatisfied((ModelElement) m)) + { } + else + { return false; } + } + } + } + return res; + } + + public boolean stereotypeConditionSatisfied(ModelElement m) + { if (m.hasStereotype(stereotype)) + { return positive; } + return false; + } + + public boolean conditionSatisfied(Type t) + { if ("class".equals(stereotype.toLowerCase()) && t.isEntityType()) + { return positive; } + if ("enumerated".equals(stereotype.toLowerCase()) && t.isEnumeratedType()) + { return positive; } + if ("collection".equals(stereotype.toLowerCase()) && t.isCollectionType()) + { return positive; } + if ("sequence".equals(stereotype.toLowerCase()) && t.isSequenceType()) + { return positive; } + if ("set".equals(stereotype.toLowerCase()) && t.isSetType()) + { return positive; } + if ("class".equals(stereotype.toLowerCase()) && !(t.isEntityType())) + { return !positive; } + if ("enumerated".equals(stereotype.toLowerCase()) && !(t.isEnumeratedType())) + { return !positive; } + if ("collection".equals(stereotype.toLowerCase()) && !(t.isCollectionType())) + { return !positive; } + if ("sequence".equals(stereotype.toLowerCase()) && !(t.isSequenceType())) + { return !positive; } + if ("set".equals(stereotype.toLowerCase()) && !(t.isSetType())) + { return !positive; } + return false; + } + + public boolean conditionSatisfied(Attribute a) + { if ("primary".equals(stereotype.toLowerCase()) && a.isPrimaryAttribute()) + { return positive; } + if (a.hasStereotype(stereotype)) + { return positive; } + return false; + } + + public boolean conditionSatisfied(Expression e) + { Type t = e.getType(); + + if (t == null) + { System.err.println("!! ERROR: null type in: " + e); + return false; + } + + String tname = t.getName(); + + if ("Set".equals(stereotype)) + { if (positive) + { return "Set".equals(tname); } + else + { return !("Set".equals(tname)); } + } + else if ("Sequence".equals(stereotype)) + { if (positive) + { return "Sequence".equals(tname); } + else + { return !("Sequence".equals(tname)); } + } + else if ("collection".equals(stereotype.toLowerCase())) + { if (positive) + { return ("Set".equals(tname) || "Sequence".equals(tname)); } + else + { return !("Set".equals(tname)) && !("Sequence".equals(tname)); } + } + else if ("String".equals(stereotype)) + { if (positive) + { return "String".equals(tname); } + else + { return !("String".equals(tname)); } + } + else if ("numeric".equals(stereotype)) + { if (positive) + { return t.isNumericType(); } + else + { return !(t.isNumericType()); } + } + else if ("object".equals(stereotype)) + { if (positive) + { return t.isEntityType(); } + else + { return !(t.isEntityType()); } + } + else if ("enumerated".equals(stereotype)) + { if (positive) + { return t.isEnumeratedType(); } + else + { return !(t.isEnumeratedType()); } + } + else if ("enumerationLiteral".equals(stereotype)) + { if (positive) + { return t.isEnumeratedType() && t.hasValue(e); } + else + { return !(t.isEnumeratedType() && t.hasValue(e)); } + } + else if ("classId".equals(stereotype)) + { if (positive) + { return e.umlkind == Expression.CLASSID; } + else + { return e.umlkind != Expression.CLASSID; } + } + else if ("value".equals(stereotype)) + { if (positive) + { return e.umlkind == Expression.VALUE; } + else + { return e.umlkind != Expression.VALUE; } + } + else if ("variable".equals(stereotype)) + { if (positive) + { return e.umlkind == Expression.VARIABLE; } + else + { return e.umlkind != Expression.VARIABLE; } + } + return false; + } + + public boolean conditionSatisfied(Statement e) + { if (e instanceof AssignStatement) + { AssignStatement st = (AssignStatement) e; + Expression left = st.getLeft(); + return conditionSatisfied(left); + } + return false; + } // and for other kinds of statement also +} + diff --git a/CGRule.java b/CGRule.java new file mode 100644 index 00000000..a72a0ffe --- /dev/null +++ b/CGRule.java @@ -0,0 +1,675 @@ +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ +/* Package: Code Generation */ + +import java.util.Vector; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +public class CGRule +{ String lhs; + String rhs; + Vector variables; // The _i in lhs -- + // no additional _i should be in rhs + Vector metafeatures; // The _i`f in rhs + String lhsop = ""; + Vector conditions; + String lhspattern = ""; // The LHS string as a regex pattern + Vector lhspatternlist = new Vector(); + + public CGRule(Expression lexp, Expression rexp, Vector whens) + { Vector lvars = lexp.metavariables(); + Vector rvars = rexp.metavariables(); + + if (lvars.containsAll(rvars)) {} + else + { System.err.println("!! Error: some extra metavariables on RHS of " + lexp + " |--> " + rexp); } + lhs = lexp + ""; + rhs = rexp + ""; + variables = lvars; + conditions = whens; + metafeatures = metafeatures(rhs); + } + + public CGRule(Expression lexp, String rgt, Vector whens) + { variables = lexp.metavariables(); + lhs = lexp + ""; + rhs = rgt; + + Vector rvariables = metavariables(rgt); + if (variables.containsAll(rvariables)) { } + else + { System.err.println("!! Error: some extra metavariables on RHS of " + this); } + + conditions = whens; + metafeatures = metafeatures(rhs); + } + + public CGRule(Expression lexp, String rgt) + { variables = lexp.metavariables(); + lhs = lexp + ""; + rhs = rgt; + + Vector rvariables = metavariables(rgt); + if (variables.containsAll(rvariables)) { } + else + { System.err.println("!! Error: some extra metavariables on RHS of " + this); } + + conditions = new Vector(); + metafeatures = metafeatures(rhs); + } + + public CGRule(Statement lexp, String rgt, Vector whens) + { variables = lexp.metavariables(); + lhs = lexp + ""; + rhs = rgt; + + Vector rvariables = metavariables(rgt); + if (variables.containsAll(rvariables)) { } + else + { System.err.println("!! Error: some extra metavariables on RHS of " + this); } + + conditions = whens; + metafeatures = metafeatures(rhs); + } + + public CGRule(Statement lexp, String rgt) + { variables = lexp.metavariables(); + lhs = lexp + ""; + rhs = rgt; + + Vector rvariables = metavariables(rgt); + if (variables.containsAll(rvariables)) { } + else + { System.err.println("!! Error: some extra metavariables on RHS of " + this); } + + conditions = new Vector(); + metafeatures = metafeatures(rhs); + } + + public CGRule(Type lexp, String rgt, Vector whens) + { variables = lexp.metavariables(); + lhs = lexp + ""; + rhs = rgt; + + Vector rvariables = metavariables(rgt); + if (variables.containsAll(rvariables)) { } + else + { System.err.println("!! Error: some extra metavariables on RHS of " + this); } + + conditions = whens; + metafeatures = metafeatures(rhs); + } + + + public CGRule(Type lexp, String rgt) + { variables = lexp.metavariables(); + lhs = lexp + ""; + rhs = rgt; + + Vector rvariables = metavariables(rgt); + if (variables.containsAll(rvariables)) { } + else + { System.err.println("!! Error: some extra metavariables on RHS of " + this); } + + conditions = new Vector(); + metafeatures = metafeatures(rhs); + } + + public CGRule(String ls, String rs, Vector vs, Vector whens) + { lhs = ls; + rhs = rs; + variables = vs; + + Vector rvariables = metavariables(rs); + if (variables.containsAll(rvariables)) { } + else + { System.err.println("!! Error: some extra metavariables on RHS of " + this); } + + conditions = whens; + metafeatures = metafeatures(rhs); + } + + public int variableCount() + { if (variables == null) + { return 0; } + return variables.size(); + } + + public boolean hasVariables() + { return variables != null && variables.size() > 0; } + + public static Vector metavariables(String str) + { Vector res = new Vector(); + for (int i = 1; i < 10; i++) + { String var = "_" + i; + if (str.indexOf(var) > -1) + { res.add(var); } + } + return res; + } + + public static Vector metafeatures(String str) + { Vector res = new Vector(); + for (int i = 1; i < 10; i++) + { String var = "_" + i + "`"; + if (str.indexOf(var) > -1) + { int j = str.indexOf(var); + String f = var; + System.out.println(">>> found metafeature for " + var); + + boolean found = false; + for (int k = j+3; k < str.length() && !found; k++) + { if (Character.isLetter(str.charAt(k))) + { f = f + str.charAt(k); } + else + { res.add(f); + found = true; + } + } + } + } + return res; + } // look for identifier starting from the ` + + public String toString() + { String res = lhs + " |-->" + rhs; + if (conditions != null && conditions.size() > 0) + { res = res + " "; + for (int i = 0; i < conditions.size(); i++) + { CGCondition cnd = (CGCondition) conditions.get(i); + res = res + cnd; + if (i < conditions.size() - 1) + { res = res + ", "; } + } + } + return res; + } + + + public void addCondition(CGCondition cond) + { conditions.add(cond); } + + public boolean hasCondition(String prop) + { for (int x = 0; x < conditions.size(); x++) + { CGCondition cond = (CGCondition) conditions.get(x); + if (prop.equals(cond.stereotype) && cond.positive) + { return true; } + } + return false; + } + + public boolean hasNegativeCondition(String prop) + { for (int x = 0; x < conditions.size(); x++) + { CGCondition cond = (CGCondition) conditions.get(x); + if (prop.equals(cond.stereotype) && !cond.positive) + { return true; } + } + return false; + } + + public boolean hasCondition(String prop, String var) + { for (int x = 0; x < conditions.size(); x++) + { CGCondition cond = (CGCondition) conditions.get(x); + if (prop.equals(cond.stereotype) && var.equals(cond.variable) && cond.positive) + { return true; } + } + return false; + } + + public boolean satisfiesConditions(Vector args) + { return CGCondition.conditionsSatisfied(conditions,args); } + + public String applyRule(Vector args) + { // substitute variables[i] by args[i] in rhs + String res = rhs + ""; + for (int x = 0; x < args.size() && x < variables.size(); x++) + { String var = (String) variables.get(x); + String arg = (String) args.get(x); + String arg1 = correctNewlines(arg); + // System.out.println(">--> Replacing " + var + " by " + arg1); + res = res.replaceAll(var,arg1); + } + return res; + } + + public String applyRule(Vector args, Vector eargs, CGSpec cgs) + { // substitute metafeatures[j] by the value of eargs[j] metafeature + // substitute variables[i] by args[i] in rhs + + String res = rhs + ""; + for (int j = 0; j < metafeatures.size(); j++) + { String mf = (String) metafeatures.get(j); + String mfvar = mf.substring(0,2); + String mffeat = mf.substring(3,mf.length()); + int k = Integer.parseInt(mfvar.charAt(1) + ""); + if (k >= 1 && k <= eargs.size()) + { Object obj = eargs.get(k-1); + // System.out.println(">>> Applying metafeature " + mffeat + " to " + obj); + + + if ("defaultValue".equals(mffeat) && obj instanceof Type) + { Type ee = (Type) obj; + Expression exp = ee.getDefaultValueExpression(); + if (exp != null) + { String repl = exp.cg(cgs); + String repl1 = correctNewlines(repl); + System.out.println(">--> Replacing " + mf + " by " + repl1); + res = res.replaceAll(mf,repl1); + } + } + else if ("elementType".equals(mffeat) && obj instanceof Expression) + { Expression e = (Expression) obj; + Type t = e.getElementType(); + if (t != null) + { String repl = t.cg(cgs); + String repl1 = correctNewlines(repl); + // System.out.println(">--> Replacing metafeature " + mf + " by " + repl1); + res = res.replaceAll(mf,repl1); + } + } + else if ("elementType".equals(mffeat) && obj instanceof Type) + { Type ee = (Type) obj; + Type t = ee.getElementType(); + if (t != null) + { String repl = t.cg(cgs); + String repl1 = correctNewlines(repl); + // System.out.println(">--> Replacing " + mf + " by " + repl1); + res = res.replaceAll(mf,repl1); + } + } + else if ("elementType".equals(mffeat) && obj instanceof Attribute) + { Attribute att = (Attribute) obj; + Type t = att.getElementType(); + if (t != null) + { String repl = t.cg(cgs); + String repl1 = correctNewlines(repl); + // System.out.println(">--> Replacing " + mf + " by " + repl1); + res = res.replaceAll(mf,repl1); + } + } + else if ("type".equals(mffeat) && obj instanceof Expression) + { Expression e = (Expression) obj; + Type t = e.getType(); + if (t != null) + { String repl = t.cg(cgs); + String repl1 = correctNewlines(repl); + // System.out.println(">--> Replacing " + mf + " by " + repl1); + res = res.replaceAll(mf,repl1); + } + } + else if ("type".equals(mffeat) && obj instanceof Attribute) + { Attribute att = (Attribute) obj; + Type t = att.getType(); + if (t != null) + { String repl = t.cg(cgs); + String repl1 = correctNewlines(repl); + // System.out.println(">--> Replacing " + mf + " by " + repl1); + res = res.replaceAll(mf,repl1); + } + } + else if ("type".equals(mffeat) && obj instanceof BehaviouralFeature) + { BehaviouralFeature e = (BehaviouralFeature) obj; + Type t = e.getType(); + if (t != null) + { String repl = t.cg(cgs); + String repl1 = correctNewlines(repl); + // System.out.println(">--> Replacing " + mf + " by " + repl1); + res = res.replaceAll(mf,repl1); + } + } + else if ("typename".equals(mffeat) && obj instanceof Expression) + { Expression e = (Expression) obj; + Type t = e.getType(); + if (t != null) + { String repl = t.getName(); + res = res.replaceAll(mf,repl); + } + } + else if ("typename".equals(mffeat) && obj instanceof Attribute) + { Attribute att = (Attribute) obj; + Type t = att.getType(); + if (t != null) + { String repl = t.getName(); + res = res.replaceAll(mf,repl); + } + } + else if ("typename".equals(mffeat) && obj instanceof BehaviouralFeature) + { BehaviouralFeature e = (BehaviouralFeature) obj; + Type t = e.getType(); + if (t != null) + { String repl = t.getName(); + res = res.replaceAll(mf,repl); + } + } + else if ("elementType".equals(mffeat) && obj instanceof BehaviouralFeature) + { BehaviouralFeature bf = (BehaviouralFeature) obj; + Type t = bf.getElementType(); + if (t != null) + { String repl = t.cg(cgs); + String repl1 = correctNewlines(repl); + // System.out.println(">--> Replacing " + mf + " by " + repl1); + res = res.replaceAll(mf,repl1); + } + } + else if ("owner".equals(mffeat) && obj instanceof Attribute) + { Attribute att = (Attribute) obj; + Entity et = att.getOwner(); + if (et != null) + { String repl = et.cg(cgs); + String repl1 = correctNewlines(repl); + // System.out.println(">--> Replacing " + mf + " by " + repl1); + res = res.replaceAll(mf,repl1); + } + } + else if ("owner".equals(mffeat) && obj instanceof BehaviouralFeature) + { BehaviouralFeature e = (BehaviouralFeature) obj; + Entity et = e.getOwner(); + if (et != null) + { String repl = et.cg(cgs); + String repl1 = correctNewlines(repl); + // System.out.println(">--> Replacing " + mf + " by " + repl1); + res = res.replaceAll(mf,repl1); + } + } + else if ("ownername".equals(mffeat) && obj instanceof Attribute) + { Attribute att = (Attribute) obj; + Entity et = att.getOwner(); + if (et != null) + { String repl = et.getName(); + String repl1 = correctNewlines(repl); + // System.out.println(">--> Replacing " + mf + " by " + repl1); + res = res.replaceAll(mf,repl1); + } + } + else if ("ownername".equals(mffeat) && obj instanceof BehaviouralFeature) + { BehaviouralFeature e = (BehaviouralFeature) obj; + Entity et = e.getOwner(); + if (et != null) + { String repl = et.getName(); + String repl1 = correctNewlines(repl); + // System.out.println(">--> Replacing " + mf + " by " + repl1); + res = res.replaceAll(mf,repl1); + } + } + else if ("name".equals(mffeat) && obj instanceof ModelElement) + { ModelElement e = (ModelElement) obj; + String repl = e.getName(); + if (repl != null) + { String repl1 = correctNewlines(repl); + // System.out.println(">--> Replacing " + mf + " by " + repl1); + res = res.replaceAll(mf,repl1); + } + } + else if (CSTL.hasTemplate(mffeat + ".cstl")) + { CGSpec template = CSTL.getTemplate(mffeat + ".cstl"); + System.out.println(">>> Applying template " + mffeat + " to " + obj); + + String repl = null; + if (obj instanceof ModelElement) + { ModelElement e = (ModelElement) obj; + repl = e.cg(template); + } + else if (obj instanceof Vector) + { Vector v = (Vector) obj; + repl = ""; + for (int p = 0; p < v.size(); p++) + { ModelElement kme = (ModelElement) v.get(p); + repl = repl + kme.cg(template); + } + } + + if (repl != null) + { String repl1 = correctNewlines(repl); + res = res.replaceAll(mf,repl1); + } // _1`file for template file.cstl + } + } + } + + // Should check for satisfaction of conditions *after* such substitutions + + // Extend this to allow users to define their own metafeatures in the specification + // def: _x`f = _x.expr for some abstract syntax OCL expr. + + + for (int x = 0; x < args.size() && x < variables.size(); x++) + { String var = (String) variables.get(x); + String arg = (String) args.get(x); + String arg1 = correctNewlines(arg); + // System.out.println(">--> Replacing " + var + " by " + arg1); + res = res.replaceAll(var,arg1); + } + return res; + } + + public String applyTextRule(String actualText) + { String res = "" + rhs; + // lhspattern = convertToPattern(lhs); + lhspatternlist = convertToPatterns(lhs); + + // Pattern expr = Pattern.compile(lhspattern); + + // Matcher m = expr.matcher(actualText); + + // boolean found = m.find(); + + /* if (found) + { int c = m.groupCount(); + // System.out.println(m); + + for (int x = 0; x+1 <= c && x < variables.size(); x++) + { String var = (String) variables.get(x); + String arg = m.group(x+1); + // String arg1 = correctNewlines(arg); + System.out.println(">--> Replacing " + var + " by " + arg); + res = res.replaceAll(var,arg); + } + } + else */ + + Vector matchings = new Vector(); + boolean found = checkPatternList(actualText,matchings); + if (found && matchings.size() >= variableCount() && matchings.size() > 0) + { System.out.println(">-->> Match of " + actualText + " to " + lhspatternlist); + for (int i = 0; i < variables.size(); i++) + { String var = variables.get(i) + ""; + String arg = (String) matchings.get(i); + System.out.println(">--> Replacing " + var + " by " + arg); + res = res.replaceAll(var,arg); + } + } + + return res; + } + + public static String correctNewlines(String str) + { String res = ""; + if (str.length() == 0) + { return res; } + + for (int i = 0; i < str.length() - 1; i++) + { char c1 = str.charAt(i); + char c2 = str.charAt(i+1); + if (c1 == '\\' && c2 == 'n') + { res = res + '\n'; + i++; + if (i == str.length() - 1) + { return res; } + } + else + { res = res + c1; } + } + return res + str.charAt(str.length()-1); + } + + public static Vector convertToPatterns(String str) + { Vector res = new Vector(); + + String fres = ""; + for (int i = 0; i < str.length(); i++) + { char c1 = str.charAt(i); + if (i == str.length() - 1) + { fres = fres + c1; + res.add(fres); + break; + } + char c2 = str.charAt(i+1); + if (c1 == '_' && + (c2 == '1' || c2 == '2' || c2 == '3' || c2 == '4' + || c2 == '5' || c2 == '6' || c2 == '7' || + c2 == '8' || c2 == '9')) + { res.add(fres); + res.add(("" + c1) + c2); + fres = ""; + i++; + } + else + { fres = fres + c1; } + } + System.out.println("String list = " + res); + return res; + } + + public boolean checkPatternList(String text, Vector matched) + { if (lhspatternlist == null) + { return false; } + + if (lhspatternlist.size() == 0) + { return false; } + + int pos = 0; + int i = 0; + + while (i < lhspatternlist.size()) + { String tomatch = (String) lhspatternlist.get(i); + // System.out.println(">> matching " + tomatch); + + if (tomatch.indexOf("_") >= 0) // variable + { String found = ""; + boolean continuematch = true; + + if (i < lhspatternlist.size() - 1) + { char startnext = ((String) lhspatternlist.get(i+1)).charAt(0); + int j = pos; + while (j < text.length() && continuematch) + { if (text.charAt(j) != startnext) + { found = found + text.charAt(j); + j++; + } + else if (found.length() > 0) + { System.out.println("--> Found text " + found + " for " + tomatch); + pos = j; + matched.add(found); + continuematch = false; + } + else + { return false; } + } + i++; + } + else // for the last text segment in the list + { for (int j = pos; j < text.length(); j++) + { found = found + text.charAt(j); } + + if (found.length() > 0) + { System.out.println("--> Found text " + found + " for " + tomatch); + matched.add(found); + return true; + } + else + { return false; } + } + } + else + { int spos = 0; + boolean continuematch = true; + int j = pos; + while (j < text.length() && continuematch) + { char x = text.charAt(j); + if (spos < tomatch.length()) + { if (tomatch.charAt(spos) == x) + { spos++; + pos++; + j++; + // System.out.println("Consumed " + x); + } + else + { // System.out.println("Mismatch: " + tomatch.charAt(spos) + " /= " + x); + return false; + } + } + else // go to next segment to match + { j++; + // matched.add(tomatch); + continuematch = false; + } + } + i++; + } + // i++; + } + // System.out.println(">>> Match list= " + matched); + return true; + } + + + public static String convertToPattern(String str) + { String res = ""; + if (str.length() == 0) + { return res; } + + for (int i = 0; i < str.length(); i++) + { char c1 = str.charAt(i); + if (c1 == '(') + { res = res + "\\("; } + else if (c1 == ')') + { res = res + "\\)"; } + else if (c1 == '[' || c1 == ']' || + c1 == '*' || c1 == '.' || c1 == '?' || c1 == '{' || + c1 == '}') + { res = res + '\\' + c1; } + else + { res = res + c1; } + } + + String fres = ""; + for (int i = 0; i < res.length() - 1; i++) + { char c1 = res.charAt(i); + char c2 = res.charAt(i+1); + if (c1 == '_' && + (c2 == '1' || c2 == '2' || c2 == '3' || c2 == '4' + || c2 == '5' || c2 == '6' || c2 == '7' || + c2 == '8' || c2 == '9')) + { fres = fres + "(.+)"; + i++; + } + else + { fres = fres + c1; } + } + return fres + res.charAt(res.length()-1); + } + + public static void main(String[] args) + { // System.out.println(metafeatures("for (_1`elementType _2 : _1) do { _3 }")); + Vector vars = new Vector(); + vars.add("_1"); + vars.add("_2"); + CGRule r = new CGRule("createByPK_1(_2)", "_1.createByPK_1(_2)", vars, new Vector()); + String rr = r.applyTextRule("createByPKB(x)"); + System.out.println(rr); + + Vector patts = convertToPatterns("createByPK_1(_2)"); + r.lhspatternlist = patts; + Vector matched = new Vector(); + boolean b = r.checkPatternList("createByPKB(x)", matched); + System.out.println(b); + } +} diff --git a/CGSpec.java b/CGSpec.java new file mode 100644 index 00000000..8628f36a --- /dev/null +++ b/CGSpec.java @@ -0,0 +1,822 @@ +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ +/* Package: Code Generation */ + +import java.util.Vector; +import java.io.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class CGSpec +{ Vector typeDefinitionRules; + Vector typeUseRules; + Vector basicExpressionRules; + Vector unaryExpressionRules; + Vector conditionalExpressionRules; + Vector binaryExpressionRules; + Vector setExpressionRules; + Vector statementRules; + Vector classRules; + Vector packageRules; + Vector usecaseRules; + Vector attributeRules; + Vector parameterRules; + Vector operationRules; + Vector enumerationRules; + Vector textRules; + + public CGSpec() + { typeDefinitionRules = new Vector(); + typeUseRules = new Vector(); + basicExpressionRules = new Vector(); + unaryExpressionRules = new Vector(); + binaryExpressionRules = new Vector(); + conditionalExpressionRules = new Vector(); + setExpressionRules = new Vector(); + statementRules = new Vector(); + classRules = new Vector(); + packageRules = new Vector(); + usecaseRules = new Vector(); + attributeRules = new Vector(); + parameterRules = new Vector(); + operationRules = new Vector(); + enumerationRules = new Vector(); + textRules = new Vector(); + } + + public void addTypeUseRule(CGRule r) + { typeUseRules.add(r); } + + public void addUnaryExpressionRule(CGRule r) + { unaryExpressionRules.add(r); } + + public void addBinaryExpressionRule(CGRule r) + { binaryExpressionRules.add(r); } + + public void addSetExpressionRule(CGRule r) + { setExpressionRules.add(r); } + + public void addBasicExpressionRule(CGRule r) + { basicExpressionRules.add(r); } + + public void addConditionalExpressionRule(CGRule r) + { conditionalExpressionRules.add(r); } + + public void addStatementRule(CGRule r) + { statementRules.add(r); } + + + public void addClassRule(CGRule r) + { classRules.add(r); } + + public void addPackageRule(CGRule r) + { r.metafeatures = r.metafeatures(r.rhs); + packageRules.add(r); + } + + public void addUseCaseRule(CGRule r) + { usecaseRules.add(r); } + + public void addAttributeRule(CGRule r) + { attributeRules.add(r); } + + public void addParameterRule(CGRule r) + { parameterRules.add(r); } + + public void addOperationRule(CGRule r) + { operationRules.add(r); } + + public void addEnumerationRule(CGRule r) + { enumerationRules.add(r); } + + public void addTextRule(CGRule r) + { // r.lhspattern = r.convertToPattern(r.lhs); + // r.lhspatternlist = r.convertToPatterns(r.lhs); + textRules.add(r); + } + + public String toString() + { String res = ""; + + if (packageRules.size() > 0) + { res = res + "Package::\n"; + for (int x = 0; x < packageRules.size(); x++) + { CGRule r = (CGRule) packageRules.get(x); + res = res + r + "\n"; + } + } + + res = res + "\n"; + + if (enumerationRules.size() > 0) + { res = res + "Enumeration::\n"; + for (int x = 0; x < enumerationRules.size(); x++) + { CGRule r = (CGRule) enumerationRules.get(x); + res = res + r + "\n"; + } + } + res = res + "\n"; + + if (typeUseRules.size() > 0) + { res = res + "Type::\n"; + for (int x = 0; x < typeUseRules.size(); x++) + { CGRule r = (CGRule) typeUseRules.get(x); + res = res + r + "\n"; + } + } + res = res + "\n"; + + if (classRules.size() > 0) + { res = res + "Class::\n"; + for (int x = 0; x < classRules.size(); x++) + { CGRule r = (CGRule) classRules.get(x); + res = res + r + "\n"; + } + } + + res = res + "\n"; + + if (attributeRules.size() > 0) + { res = res + "Attribute::\n"; + for (int x = 0; x < attributeRules.size(); x++) + { CGRule r = (CGRule) attributeRules.get(x); + res = res + r + "\n"; + } + } + + res = res + "\n"; + + if (operationRules.size() > 0) + { res = res + "Operation::\n"; + for (int x = 0; x < operationRules.size(); x++) + { CGRule r = (CGRule) operationRules.get(x); + res = res + r + "\n"; + } + } + + res = res + "\n"; + + if (parameterRules.size() > 0) + { res = res + "Parameter::\n"; + for (int x = 0; x < parameterRules.size(); x++) + { CGRule r = (CGRule) parameterRules.get(x); + res = res + r + "\n"; + } + } + + res = res + "\n"; + + if (statementRules.size() > 0) + { res = res + "Statement::\n"; + for (int x = 0; x < statementRules.size(); x++) + { CGRule r = (CGRule) statementRules.get(x); + res = res + r + "\n"; + } + } + + res = res + "\n"; + + if (basicExpressionRules.size() > 0) + { res = res + "BasicExpression::\n"; + for (int x = 0; x < basicExpressionRules.size(); x++) + { CGRule r = (CGRule) basicExpressionRules.get(x); + res = res + r + "\n"; + } + } + + res = res + "\n"; + + if (unaryExpressionRules.size() > 0) + { res = res + "UnaryExpression::\n"; + for (int x = 0; x < unaryExpressionRules.size(); x++) + { CGRule r = (CGRule) unaryExpressionRules.get(x); + res = res + r + "\n"; + } + } + + res = res + "\n"; + + if (binaryExpressionRules.size() > 0) + { res = res + "BinaryExpression::\n"; + for (int x = 0; x < binaryExpressionRules.size(); x++) + { CGRule r = (CGRule) binaryExpressionRules.get(x); + res = res + r + "\n"; + } + } + res = res + "\n"; + + if (setExpressionRules.size() > 0) + { res = res + "SetExpression::\n"; + for (int x = 0; x < setExpressionRules.size(); x++) + { CGRule r = (CGRule) setExpressionRules.get(x); + res = res + r + "\n"; + } + } + + res = res + "\n"; + + if (conditionalExpressionRules.size() > 0) + { res = res + "ConditionalExpression::\n"; + for (int x = 0; x < conditionalExpressionRules.size(); x++) + { CGRule r = (CGRule) conditionalExpressionRules.get(x); + res = res + r + "\n"; + } + } + + res = res + "\n"; + + if (usecaseRules.size() > 0) + { res = res + "UseCase::\n"; + for (int x = 0; x < usecaseRules.size(); x++) + { CGRule r = (CGRule) usecaseRules.get(x); + res = res + r + "\n"; + } + } + + res = res + "\n"; + + if (textRules.size() > 0) + { res = res + "Text::\n"; + for (int x = 0; x < textRules.size(); x++) + { CGRule r = (CGRule) textRules.get(x); + res = res + r + "\n"; + } + } + + res = res + "\n"; + + return res; + } + + public void transformPackage(String typestring, String classesstring, String ucstring, + Vector types, Vector entities, Vector useCases, + PrintWriter out) + { if (packageRules.size() > 0) + { CGRule r = (CGRule) packageRules.get(0); + r.metafeatures = r.metafeatures(r.rhs); + // System.out.println(">>> " + r + " metafeatures = " + r.metafeatures); + + Vector args = new Vector(); + Vector eargs = new Vector(); + + args.add("MainApp"); + args.add(typestring); + args.add(classesstring); + args.add(ucstring); + + eargs.add("MainApp"); + eargs.add(types); + eargs.add(entities); + eargs.add(useCases); + + String res = r.applyRule(args,eargs,this); + displayText(res,out); + return; + } + displayText(typestring,out); + out.println(); + out.println(); + displayText(classesstring,out); + } + + private void displayText(String str, PrintWriter out) + { int n = str.length(); + StringBuffer res = new StringBuffer(); + + for (int i = 0; i < n; i++) + { char x = str.charAt(i); + if (x == '\n') + { out.println(res); + res = new StringBuffer(); + } + else if (i < n-1 && x == '\\' && str.charAt(i+1) == 'n') + { out.println(res); + res = new StringBuffer(); + i++; + } + else + { res.append(x); } + } + out.println(res); + } + + public CGRule matchedEnumerationRule(Object t, String typetext) + { for (int x = 0; x < enumerationRules.size(); x++) + { CGRule r = (CGRule) enumerationRules.get(x); + if (typetext.equals(r.lhs)) + { return r; } // exact match + else if (t instanceof Type && + ((Type) t).isEnumeratedType() && r.lhs.startsWith("enumeration")) + { return r; } + else if (t instanceof Vector && r.lhs.startsWith("literal") && r.lhs.indexOf(",") > -1) + { return r; } + else if (t instanceof EnumLiteral && r.lhs.startsWith("literal") && + r.lhs.indexOf(",") < 0) + { return r; } + } + return null; + } + + public CGRule matchedTypeUseRule(Type t, String typetext) + { for (int x = 0; x < typeUseRules.size(); x++) + { CGRule r = (CGRule) typeUseRules.get(x); + if (typetext.equals(r.lhs)) + { return r; } // exact match + else if (t.isMapType() && r.lhs.startsWith("Map")) + { return r; } + else if (t.isEnumeratedType() && r.hasCondition("enumerated")) + { return r; } + else if (t.isEntityType() && r.hasCondition("class")) + { return r; } + else if (t.isSetType() && r.lhs.startsWith("Set")) + { return r; } + else if (t.isSequenceType() && r.lhs.startsWith("Sequence")) + { return r; } + } + return null; + } // _1 binds to type or elementType + + public CGRule matchedUnaryExpressionRule(UnaryExpression e, String etext) + { String op = e.getOperator(); + Expression arg = e.getArgument(); + Vector args = new Vector(); + args.add(arg); + + for (int x = 0; x < unaryExpressionRules.size(); x++) + { CGRule r = (CGRule) unaryExpressionRules.get(x); + CGRule selected = null; + + if (etext.equals(r.lhs)) + { selected = r; } // exact match + else if (op.startsWith("->") && r.lhs.endsWith(op + "()")) + { selected = r; } + else if (etext.startsWith(op) && r.lhs.startsWith(op)) + { selected = r; } + + if (selected != null && selected.satisfiesConditions(args)) + { return selected; } + } + return null; + } // _1 binds to argument + + public CGRule matchedStatementRule(Statement e, String etext) + { String op = e.getOperator(); + + for (int x = 0; x < statementRules.size(); x++) + { CGRule r = (CGRule) statementRules.get(x); + if (etext.equals(r.lhs)) + { return r; } // exact match + else if (op.equals("while") && r.lhs.startsWith(op)) + { return r; } + else if (op.equals("for") && r.lhs.startsWith(op)) + { return r; } + else if (op.equals("return") && r.lhs.startsWith(op)) + { if (((ReturnStatement) e).hasValue() && r.hasVariables()) + { return r; } + else + { if (!((ReturnStatement) e).hasValue() && !r.hasVariables()) + { return r; } + } + } + else if (op.equals("if") && r.lhs.startsWith(op) && (e instanceof ConditionalStatement)) + { ConditionalStatement cs = (ConditionalStatement) e; + // if ((cs.getTest() + "").equals("true") && + // r.lhs.startsWith("if true")) + // { return r; } + // else if ((cs.getTest() + "").equals("false") && + // r.lhs.startsWith("if false")) + // { return r; } + // else + { return r; } + } + else if (op.equals("if") && r.lhs.startsWith(op) && (e instanceof IfStatement)) + { // IfStatement cs = (IfStatement) e; + // if ((cs.getTest() + "").equals("true") && + // r.lhs.startsWith("if true")) + // { return r; } + // else if ((cs.getTest() + "").equals("false") && + // r.lhs.startsWith("if false")) + // { return r; } + // else + { return r; } + } + else if (op.equals("break") && r.lhs.startsWith(op)) + { return r; } + else if (e instanceof SequenceStatement && (r.lhs.indexOf(";") > -1)) + { return r; } + else if (op.equals("var") && r.lhs.startsWith(op)) + { Vector args = ((CreationStatement) e).cgparameters(); + if (r.satisfiesConditions(args)) + { return r; } + } + else if (op.equals(":=") && (r.lhs.indexOf(op) > -1)) + { Vector args = ((AssignStatement) e).cgparameters(); + if (r.satisfiesConditions(args)) + { return r; } + } + else if (op.equals("execute") && r.lhs.startsWith(op)) + { Vector args = ((ImplicitInvocationStatement) e).cgparameters(); + if (r.satisfiesConditions(args)) + { return r; } + } + else if (op.equals("call") && r.lhs.startsWith(op)) + { Vector args = ((InvocationStatement) e).cgparameters(); + if (r.satisfiesConditions(args)) + { return r; } + } + } + return null; + } + + public CGRule matchedBinaryExpressionRule(BinaryExpression e, String etext) + { String op = e.getOperator(); + Vector args = new Vector(); + if ("|".equals(op)) + { op = "->select"; + BinaryExpression beleft = (BinaryExpression) e.getLeft(); + args.add(beleft.getRight()); + args.add(beleft.getLeft()); + args.add(e.getRight()); + } + else if ("|C".equals(op)) + { op = "->collect"; + BinaryExpression beleft = (BinaryExpression) e.getLeft(); + args.add(beleft.getRight()); + args.add(beleft.getLeft()); + args.add(e.getRight()); + } + else if ("|R".equals(op)) + { op = "->reject"; + BinaryExpression beleft = (BinaryExpression) e.getLeft(); + args.add(beleft.getRight()); + args.add(beleft.getLeft()); + args.add(e.getRight()); + } + if ("!".equals(op)) + { op = "->forAll"; + BinaryExpression beleft = (BinaryExpression) e.getLeft(); + args.add(beleft.getRight()); + args.add(beleft.getLeft()); + args.add(e.getRight()); + } + else if ("#".equals(op)) + { op = "->exists"; + BinaryExpression beleft = (BinaryExpression) e.getLeft(); + args.add(beleft.getRight()); + args.add(beleft.getLeft()); + args.add(e.getRight()); + } + else if ("#1".equals(op)) + { op = "->exists1"; + BinaryExpression beleft = (BinaryExpression) e.getLeft(); + args.add(beleft.getRight()); + args.add(beleft.getLeft()); + args.add(e.getRight()); + } + else if ("|A".equals(op)) + { op = "->any"; + BinaryExpression beleft = (BinaryExpression) e.getLeft(); + args.add(beleft.getRight()); + args.add(beleft.getLeft()); + args.add(e.getRight()); + } + else if ("->collect".equals(op) || "->reject".equals(op) || "->any".equals(op) || + "->select".equals(op) || "->exists".equals(op) || + "->exists1".equals(op) || "->forAll".equals(op) || + "->isUnique".equals(op) || "->sortedBy".equals(op)) + { args.add(e.getLeft()); + BasicExpression v = new BasicExpression("v"); + v.setType(e.getLeft().getElementType()); + args.add(v); + args.add(e.getRight()); + } // and for ->sortedBy, etc + else + { args.add(e.getLeft()); + args.add(e.getRight()); + } + + for (int x = 0; x < binaryExpressionRules.size(); x++) + { CGRule r = (CGRule) binaryExpressionRules.get(x); + CGRule selected = null; + + if (etext.equals(r.lhs)) + { selected = r; } // exact match + else if (op.startsWith("->") && (r.lhs.indexOf(op) > -1)) + { selected = r; } + else if (r.lhs.indexOf(op) > -1) + { selected = r; } + + if (selected != null && selected.satisfiesConditions(args)) + { return selected; } + } + return null; + } // _1 binds to left, _2 to right + + public CGRule matchedConditionalExpressionRule(ConditionalExpression e, String etext) + { // Vector args = new Vector(); + // args.add(e.getTest()); + // args.add(e.getIfExp()); + // args.add(e.getElseExp()); + + for (int x = 0; x < conditionalExpressionRules.size(); x++) + { CGRule r = (CGRule) conditionalExpressionRules.get(x); + CGRule selected = null; + + // if ((e.getTest() + "").equals("true") && r.lhs.startsWith("if true")) + // { selected = r; } // exact match + // else if ((e.getTest() + "").equals("false") && r.lhs.startsWith("if false")) + // { selected = r; } + // else + { selected = r; } + + if (selected != null) + { return selected; } + } + return null; + } + + public CGRule matchedBasicExpressionRule(BasicExpression e, String etext) + { Expression obj = e.getObjectRef(); + Expression ind = e.getArrayIndex(); + Vector pars = e.getParameters(); + + + for (int x = 0; x < basicExpressionRules.size(); x++) + { CGRule r = (CGRule) basicExpressionRules.get(x); + CGRule selected = null; + Vector args = new Vector(); + + if (etext.equals(r.lhs) && r.variableCount() == 0) + { return r; } // exact match + else if (e.data.equals("allInstances") && r.lhs.trim().endsWith("allInstances")) + { return r; } + else if (pars != null && pars.size() == 2 && + (e + "").startsWith("Integer.subrange(") && + r.lhs.startsWith("Integer.subrange(")) + { return r; } + else if (pars != null && pars.size() == 4 && + e.data.equals("Sum") && "Integer".equals(e.getObjectRef() + "") && + r.lhs.startsWith("Integer.Sum(")) + { return r; } + else if (pars != null && pars.size() == 4 && + e.data.equals("Prd") && "Integer".equals(e.getObjectRef() + "") && + r.lhs.startsWith("Integer.Prd(")) + { return r; } + else if (pars != null && pars.size() == 2 && + e.data.equals("subrange") && r.lhs.startsWith("_1.subrange(")) + { return r; } + else if (pars != null && pars.size() == 2 && + e.data.equals("insertAt") && r.lhs.startsWith("_1.insertAt(")) + { return r; } + else if (ind != null && pars == null && + r.lhs.trim().endsWith("]") && (r.lhs.indexOf("[") > -1)) + { selected = r; + args.add(e); + args.add(ind); // condition is on _2 + } + else if (ind == null && obj != null && pars == null && r.lhs.indexOf(".") > -1 && + r.lhs.indexOf("(") < 0 && !(r.lhs.endsWith("allInstances"))) + { return r; } + else if (obj != null && ind == null && pars != null && r.lhs.equals("_1._2(_3)")) + { return r; } + else if (obj == null && ind == null && pars != null && r.lhs.equals("_1(_2)")) + { return r; } + else if (obj == null && ind == null && pars == null && r.lhs.equals("_1")) + { return r; } + + if (selected != null && selected.satisfiesConditions(args)) + { return selected; } + } + return null; + } // _1 binds to objectRef or left part, _2 to right part/index + + public CGRule matchedSetExpressionRule(SetExpression e, String etext) + { boolean ordered = e.isOrdered(); + Vector elems = e.getElements(); + + for (int x = 0; x < setExpressionRules.size(); x++) + { CGRule r = (CGRule) setExpressionRules.get(x); + if (etext.equals(r.lhs)) + { return r; } // exact match + else if (etext.startsWith("Set{") && etext.endsWith("}") && + r.lhs.startsWith("Set{") && r.lhs.endsWith("}")) + { if (elems.size() == 0 && r.variables.size() == 0) + { return r; } // r is empty set -- just white space in lhs between {} + else if (elems.size() > 0 && r.variables.size() > 0) + { return r; } + } + else if (etext.startsWith("Sequence{") && etext.endsWith("}") && + r.lhs.startsWith("Sequence{") && r.lhs.endsWith("}")) + { if (elems.size() == 0 && r.variables.size() == 0) + { return r; } // r is empty set + else if (elems.size() > 0 && r.variables.size() > 0) + { return r; } + } + else if (etext.startsWith("Map{") && etext.endsWith("}") && + r.lhs.startsWith("Map{") && r.lhs.endsWith("}")) + { if (elems.size() == 0 && r.variables.size() == 0) + { return r; } // empty map + else if (elems.size() > 0 && r.variables.size() > 0) + { return r; } + } + } + return null; + } // _1 binds to elements if any + + public CGRule matchedEntityRule(Entity e, String ctext) + { Vector args = new Vector(); + args.add(e); + + CGRule selected = null; + + for (int x = 0; x < classRules.size(); x++) + { CGRule r = (CGRule) classRules.get(x); + if (ctext.equals(r.lhs)) + { selected = r; } // exact match + else if (e.isInterface() && r.lhs.indexOf("interface") > -1) + { selected = r; } + else if (e.isAbstract()) + { if (e.getSuperclass() != null && r.lhs.indexOf("abstract") > -1 && + r.lhs.indexOf("extends") > -1) + { selected = r; } + else if (e.getSuperclass() == null & r.lhs.indexOf("extends") < 0 && + e.hasInterfaces() && r.lhs.indexOf("abstract") > -1 && + r.lhs.indexOf("implements") > -1) + { selected = r; } + else if (e.getSuperclass() == null && r.lhs.indexOf("abstract") > -1 && + r.lhs.indexOf("extends") < 0) + { selected = r; } + } + else if (e.getSuperclass() != null && r.lhs.indexOf("abstract") < 0 && + r.lhs.indexOf("extends") > -1) + { selected = r; } + else if (e.getSuperclass() == null & r.lhs.indexOf("extends") < 0 && + e.hasInterfaces() && r.lhs.indexOf("abstract") < 0 && + r.lhs.indexOf("implements") > -1) + { selected = r; } + else if (e.getSuperclass() == null && r.lhs.indexOf("abstract") < 0 && + r.lhs.indexOf("extends") < 0) + { selected = r; } + + if (selected != null && selected.satisfiesConditions(args)) + { return selected; } + + } + return null; + } // _1 binds to class name + + public CGRule matchedAttributeRule(Attribute e, String ctext) + { CGRule selected = null; + + Vector args = new Vector(); + args.add(e); + args.add(e.getType()); + + for (int x = 0; x < attributeRules.size(); x++) + { CGRule r = (CGRule) attributeRules.get(x); + + if (r.lhs.indexOf("attribute") > -1) { } + else + { continue; } + + if (ctext.equals(r.lhs) && r.variableCount() == 0) + { selected = r; } // exact match + else if (e.isStatic()) + { if (r.lhs.indexOf("static") > -1) + { selected = r; } + } + else if (r.hasCondition("primary") && e.isPrimaryAttribute()) + { selected = r; } + else if (e.isUnique()) + { if (r.lhs.indexOf("identity") > -1) + { selected = r; } + } + else if (r.lhs.indexOf("identity") < 0 && r.lhs.indexOf("static") < 0) + { selected = r; } + + if (selected != null && selected.satisfiesConditions(args)) + { return selected; } + } + + return null; + } + + public CGRule matchedReferenceRule(Attribute e, String ctext) + { for (int x = 0; x < attributeRules.size(); x++) + { CGRule r = (CGRule) attributeRules.get(x); + + if (r.lhs.startsWith("reference")) + { if (e.getType() != null && e.getType().isCollectionType()) + { if (r.hasCondition("collection")) + { return r; } + else if (r.hasNegativeCondition("collection")) + { } + else + { return r; } + } + else if (e.getType() != null && !e.getType().isCollectionType()) + { if (r.hasNegativeCondition("collection")) + { return r; } + else if (r.hasCondition("collection")) + { } + else + { return r; } + } + } + } + return null; + } + + public CGRule matchedParameterRule(Attribute e, Vector rem, String ctext) + { for (int x = 0; x < parameterRules.size(); x++) + { CGRule r = (CGRule) parameterRules.get(x); + + + if (ctext.equals(r.lhs)) + { return r; } // exact match + else if (r.lhs.indexOf(",") > -1 && rem.size() > 0) + { return r; } + else if (r.lhs.indexOf(",") < 0 && rem.size() == 0) + { return r; } + } + return null; + } + + public CGRule matchedOperationRule(BehaviouralFeature e, String ctext) + { for (int x = 0; x < operationRules.size(); x++) + { CGRule r = (CGRule) operationRules.get(x); + if (ctext.equals(r.lhs)) + { return r; } // exact match + else if (e.isQuery()) + { if (r.lhs.indexOf("query") > -1) + { if (e.isStatic()) + { if (r.lhs.indexOf("static") > -1) + { return r; } + } + else if (r.lhs.indexOf("static") < 0) + { return r; } + } + } + else if (r.lhs.indexOf("operation") > -1) + { if (e.isStatic()) + { if (r.lhs.indexOf("static") > -1) + { return r; } + } + else if (r.lhs.indexOf("static") < 0) + { return r; } + } + } + return null; + } // distinguish queries and operations + + public CGRule matchedUsecaseRule(UseCase e, String ctext) + { for (int x = 0; x < usecaseRules.size(); x++) + { CGRule r = (CGRule) usecaseRules.get(x); + return r; + } + return null; + } // distinguish operation descriptions and use cases. + + public CGRule matchedTextRule(String text) + { String realtext = ""; + + /* Vector chars = new Vector(); + for (int i = 0; i < text.length(); i++) + { realtext = realtext + text.charAt(i); + chars.add(text.charAt(i)+""); + } */ + + for (int i = 0; i < textRules.size(); i++) + { CGRule r = (CGRule) textRules.get(i); + + + // String lhspattern = r.convertToPattern(r.lhs); + + // if (lhspattern != null && lhspattern.length() > 0) + // { Pattern expr = Pattern.compile(lhspattern); + + // Matcher m = expr.matcher(text); + + // boolean found = m.find(); + // System.out.println(m); + // if (found) + // { return r; } + // else + { Vector matchings = new Vector(); + boolean found = r.checkPatternList(text,matchings); + if (found) + { return r; } + } + // } + } + return null; + } + +} + diff --git a/CSTL.java b/CSTL.java new file mode 100644 index 00000000..394d1896 --- /dev/null +++ b/CSTL.java @@ -0,0 +1,193 @@ +import java.io.*; +import java.util.Vector; + + +public class CSTL +{ // All *.cstl files in output directory are loaded + + static java.util.Map templates = new java.util.HashMap(); + + public static void loadTemplates(Vector types, Vector entities) + { File dir = new File("./cg"); + String[] dirfiles = dir.list(); + for (int i = 0; i < dirfiles.length; i++) + { File sub = new File("./cg/" + dirfiles[i]); + if (sub != null && dirfiles[i].endsWith(".cstl") && + !(dirfiles[i].equals("cg.cstl"))) + { System.out.println(">>> Found CSTL template: " + dirfiles[i]); + CGSpec cg = loadCSTL(sub,types,entities); + if (cg != null) + { addTemplate(dirfiles[i],cg); } + } + } + } + + public static CGSpec loadCSTL(File file, Vector types, Vector entities) + { CGSpec res = new CGSpec(); + + BufferedReader br = null; + String s; + boolean eof = false; + + try + { br = new BufferedReader(new FileReader(file)); } + catch (FileNotFoundException _e) + { System.err.println("!! ERROR: File not found: " + file); + return null; + } + + int noflines = 0; + String mode = "none"; + + while (!eof) + { try { s = br.readLine(); } + catch (IOException _ex) + { System.out.println("ERROR!!: Reading CSTL file failed."); + return null; + } + if (s == null) + { eof = true; + break; + } + else if (s.startsWith("--")) { } + else if (s.trim().length() == 0) { } + else if (s.equals("Type::")) + { mode = "types"; } + else if (s.equals("Enumeration::")) + { mode = "enumerations"; } + else if (s.equals("Text::")) + { mode = "texts"; } + else if (s.equals("BasicExpression::")) + { mode = "basicexpressions"; } + else if (s.equals("UnaryExpression::")) + { mode = "unaryexpressions"; } + else if (s.equals("BinaryExpression::")) + { mode = "binaryexpressions"; } + else if (s.equals("SetExpression::")) + { mode = "setexpressions"; } + else if (s.equals("ConditionalExpression::")) + { mode = "conditionalexpressions"; } + else if (s.equals("Class::")) + { mode = "entities"; } + else if (s.equals("Attribute::")) + { mode = "attributes"; } + else if (s.equals("Parameter::")) + { mode = "parameters"; } + else if (s.equals("Operation::")) + { mode = "operations"; } + else if (s.equals("Statement::")) + { mode = "statements"; } + else if (s.equals("Package::")) + { mode = "packages"; } + else if (s.equals("UseCase::")) + { mode = "usecases"; } + else if ("types".equals(mode)) + { Compiler2 c = new Compiler2(); + CGRule r = c.parse_TypeCodegenerationrule(s.trim()); + if (r != null) + { res.addTypeUseRule(r); } + } + else if ("basicexpressions".equals(mode)) + { Compiler2 c = new Compiler2(); + CGRule r = c.parse_ExpressionCodegenerationrule(s.trim()); + if (r != null) + { res.addBasicExpressionRule(r); } + } + else if ("unaryexpressions".equals(mode)) + { Compiler2 c = new Compiler2(); + CGRule r = c.parse_ExpressionCodegenerationrule(s.trim()); + if (r != null) + { res.addUnaryExpressionRule(r); } + } + else if ("binaryexpressions".equals(mode)) + { Compiler2 c = new Compiler2(); + CGRule r = c.parse_ExpressionCodegenerationrule(s.trim()); + if (r != null) + { res.addBinaryExpressionRule(r); } + } + else if ("setexpressions".equals(mode)) + { Compiler2 c = new Compiler2(); + CGRule r = c.parse_ExpressionCodegenerationrule(s.trim()); + if (r != null) + { res.addSetExpressionRule(r); } + } + else if ("conditionalexpressions".equals(mode)) + { Compiler2 c = new Compiler2(); + CGRule r = c.parse_ExpressionCodegenerationrule(s.trim()); + if (r != null) + { res.addConditionalExpressionRule(r); } + } + else if ("entities".equals(mode)) + { Compiler2 c = new Compiler2(); + CGRule r = c.parse_EntityCodegenerationrule(s.trim()); + if (r != null) + { res.addClassRule(r); } + } + else if ("enumerations".equals(mode)) + { Compiler2 c = new Compiler2(); + CGRule r = c.parse_EntityCodegenerationrule(s.trim()); + if (r != null) + { res.addEnumerationRule(r); } + } + else if ("packages".equals(mode)) + { Compiler2 c = new Compiler2(); + CGRule r = c.parse_EntityCodegenerationrule(s.trim()); + if (r != null) + { res.addPackageRule(r); } + } + else if ("attributes".equals(mode)) + { Compiler2 c = new Compiler2(); + CGRule r = c.parse_AttributeCodegenerationrule(s.trim()); + if (r != null) + { res.addAttributeRule(r); } + } + else if ("operations".equals(mode)) + { Compiler2 c = new Compiler2(); + CGRule r = c.parse_OperationCodegenerationrule(s.trim()); + if (r != null) + { res.addOperationRule(r); } + } + else if ("parameters".equals(mode)) + { Compiler2 c = new Compiler2(); + CGRule r = c.parse_OperationCodegenerationrule(s.trim()); + if (r != null) + { res.addParameterRule(r); } + } + else if ("statements".equals(mode)) + { Compiler2 c = new Compiler2(); + CGRule r = c.parse_StatementCodegenerationrule(s.trim(),entities,types); + if (r != null) + { res.addStatementRule(r); } + } + else if ("usecases".equals(mode)) + { Compiler2 c = new Compiler2(); + CGRule r = c.parse_UseCaseCodegenerationrule(s.trim(),entities,types); + if (r != null) + { res.addUseCaseRule(r); } + } + else if ("texts".equals(mode)) + { Compiler2 c = new Compiler2(); + CGRule r = c.parse_TextCodegenerationrule(s.trim()); + if (r != null) + { res.addTextRule(r); } + } + } + System.out.println(">>> Parsed: " + res); + return res; + } + + + public static void addTemplate(String filename, CGSpec cg) + { templates.put(filename,cg); } + + public static boolean hasTemplate(String filename) + { CGSpec cg = (CGSpec) templates.get(filename); + if (cg != null) + { return true; } + return false; + } + + public static CGSpec getTemplate(String name) + { return (CGSpec) templates.get(name); } +} + diff --git a/CollectionTemplateExp.java b/CollectionTemplateExp.java new file mode 100644 index 00000000..2167b1ae --- /dev/null +++ b/CollectionTemplateExp.java @@ -0,0 +1,347 @@ +import java.util.Vector; + +public class CollectionTemplateExp extends TemplateExp +{ Type referredCollectionType; + // Vector member = new Vector(); // Expression or TemplateExp + Attribute member = null; + Attribute rest = null; + + public CollectionTemplateExp(Attribute bind, Expression wh, Type typ) + { super(bind,wh); + referredCollectionType = typ; + } + + /* public void addMember(Expression e) + { members.add(e); } + + public void addMember(TemplateExp e) + { members.add(e); } */ + + public void setMember(Attribute m) + { member = m; } + + public void setRest(Attribute r) + { rest = r; } + + public void setConstraint(Expression w) + { where = w; } + + public Object clone() + { Expression wclone = null; + if (where != null) + { wclone = (Expression) where.clone(); } + + CollectionTemplateExp ref = new CollectionTemplateExp(bindsTo,wclone,referredCollectionType); + /* for (int j = 0; j < members.size(); j++) + { Object m = members.get(j); + if (m instanceof Expression) + { ref.addMember((Expression) m.clone()); } + else + { ref.addMember((TemplateExp) m.clone()); } + } */ + + if (member != null) + { ref.setMember((Attribute) member.clone()); } + + if (rest != null) + { ref.setRest((Attribute) rest.clone()); } + + return ref; + } + + public boolean typeCheck(Vector types, Vector entities, Vector contexts, Vector env) + { /* for (int j = 0; j < members.size(); j++) + { Object m = members.get(j); + if (m instanceof Expression) + { ((Expression) m).typeCheck(types,entities,contexts,env); } + else + { ((TemplateExp) m).typeCheck(types,entities,contexts,env); } + } */ + + Vector newenv = new Vector(); + newenv.addAll(env); + if (member != null) + { newenv.add(member); } + if (rest != null) + { newenv.add(rest); } + + if (where != null) + { where.typeCheck(types,entities,contexts,newenv); } + + return true; + } + + public Expression toSourceExpression(Vector bound, Expression contextObj) + { BasicExpression obj = new BasicExpression(bindsTo); + // obj.setUmlKind(Expression.ROLE); + // obj.setEntity(traceent); + + Vector elems = new Vector(); + Expression res = new BasicExpression(true); + // new BinaryExpression(bindsTo); + + /* + if ("Set".equals(referredCollectionType.getName())) + { // m : obj for each m + + for (int j = 0; j < members.size(); j++) + { Object m = members.get(j); + if ("_".equals(m + "")) { continue; } + if (m instanceof Expression) + { BinaryExpression inset = new BinaryExpression(":", (Expression) m, obj); + res = Expression.simplify("&",res,inset,null); + elems.add(m); + } // add to bounds if a variable + else + { TemplateExp tm = (TemplateExp) m; + Attribute x = tm.bindsTo; + Expression xexp = new BasicExpression(x); + bound.add(x.getName()); + BinaryExpression inset = new BinaryExpression(":", xexp, obj); + res = Expression.simplify("&",res,inset,null); + elems.add(xexp); + + if (tm.isEmpty()) {} + else + { Expression andcond = tm.toSourceExpression(bound,xexp); + res = new BinaryExpression("&", res, andcond); + } + } + } + } */ + + + if ("Set".equals(referredCollectionType.getName())) + { if (member != null) + { if ("_".equals(member.getName())) {} + else + { bound.add(member.getName()); + BasicExpression rexp = new BasicExpression(member); + // rexp.setUmlKind(Expression.ROLE); + // rexp.setEntity(traceent); + + elems.add(rexp); + BinaryExpression be = new BinaryExpression(":", rexp, obj); + res = Expression.simplify("&",res,be,null); + } + } + + if (rest != null) + { if ("_".equals(rest.getName())) {} + else + { bound.add(rest.getName()); + BasicExpression rexp = new BasicExpression(rest); + // rexp.setUmlKind(Expression.ROLE); + // rexp.setEntity(traceent); + + SetExpression known = new SetExpression(elems); + BinaryExpression be = new BinaryExpression("-", obj, known); + BinaryExpression eqrest = new BinaryExpression("=", rexp, be); + res = Expression.simplify("&",res,eqrest,null); + } + } + } + else if ("Sequence".equals(referredCollectionType.getName())) + { if (member != null) + { if ("_".equals(member.getName())) {} + else + { bound.add(member.getName()); + BasicExpression rexp = new BasicExpression(member); + // rexp.setUmlKind(Expression.ROLE); + // rexp.setEntity(traceent); + + elems.add(rexp); + UnaryExpression objsize = new UnaryExpression("->size",obj); + BinaryExpression nonempty = + new BinaryExpression(">", objsize, new BasicExpression(0)); + + BinaryExpression be = new BinaryExpression("->at",obj,new BasicExpression(1)); + BinaryExpression setbe = new BinaryExpression("=", rexp, be); + res = Expression.simplify("&",res,nonempty,null); + res = Expression.simplify("&",res,setbe,null); + } + } + if (rest != null) + { if ("_".equals(rest.getName())) {} + else + { bound.add(rest.getName()); + BasicExpression rexp = new BasicExpression(rest); + // rexp.setUmlKind(Expression.ROLE); + // rexp.setEntity(traceent); + + UnaryExpression be = new UnaryExpression("->tail", obj); + BinaryExpression eqrest = new BinaryExpression("=", rexp, be); + res = Expression.simplify("&",res,eqrest,null); + } + } + } + + if (where != null) + { res = Expression.simplify("&", res, where, null); } + + return res; + } + + public Expression toGuardCondition(Vector bound, + Expression contextObj, Expression post, Entity tr) + { BasicExpression obj = new BasicExpression(bindsTo); + obj.setUmlKind(Expression.ROLE); + obj.setEntity(tr); + + Vector elems = new Vector(); + Expression res = new BinaryExpression(bindsTo); + + if ("Set".equals(referredCollectionType.getName())) + { if (member != null) + { if ("_".equals(member.getName())) {} + else + { bound.add(member.getName()); + BasicExpression rexp = new BasicExpression(member); + rexp.setUmlKind(Expression.ROLE); + rexp.setEntity(tr); + + elems.add(rexp); + BinaryExpression be = new BinaryExpression(":", rexp, obj); + res = Expression.simplify("&",res,be,null); + } + } + + if (rest != null) + { if ("_".equals(rest.getName())) {} + else + { bound.add(rest.getName()); + BasicExpression rexp = new BasicExpression(rest); + rexp.setUmlKind(Expression.ROLE); + rexp.setEntity(tr); + SetExpression known = new SetExpression(elems); + BinaryExpression be = new BinaryExpression("-", obj, known); + BinaryExpression eqrest = new BinaryExpression("=", rexp, be); + res = Expression.simplify("&",res,eqrest,null); + } + } + } + else if ("Sequence".equals(referredCollectionType.getName())) + { if (member != null) + { if ("_".equals(member.getName())) {} + else + { bound.add(member.getName()); + BasicExpression rexp = new BasicExpression(member); + // rexp.setUmlKind(Expression.ROLE); + // rexp.setEntity(traceent); + + elems.add(rexp); + UnaryExpression objsize = new UnaryExpression("->size",obj); + BinaryExpression nonempty = + new BinaryExpression(">", objsize, new BasicExpression(0)); + + BinaryExpression be = new BinaryExpression("->at",obj,new BasicExpression(1)); + BinaryExpression setbe = new BinaryExpression("=", rexp, be); + res = Expression.simplify("&",res,nonempty,null); + res = Expression.simplify("&",res,setbe,null); + } + } + if (rest != null) + { if ("_".equals(rest.getName())) {} + else + { bound.add(rest.getName()); + BasicExpression rexp = new BasicExpression(rest); + // rexp.setUmlKind(Expression.ROLE); + // rexp.setEntity(traceent); + + UnaryExpression be = new UnaryExpression("->tail", obj); + BinaryExpression eqrest = new BinaryExpression("=", rexp, be); + res = Expression.simplify("&",res,eqrest,null); + } + } + } + + + if (where != null) + { res = Expression.simplify("&", res, where, null); } + + return res; + } + + public Expression toTargetExpression(Vector bound, Expression contextObj, Expression setting) + { return new BasicExpression(true); } + + public Expression toUndoExpression(Vector bound, Expression contextObj, Expression setting) + { return new BasicExpression(true); } + + public Expression toTargetExpressionOp(Vector bound, Expression contextObj, Expression setting) + { return new BasicExpression(true); } + + public Vector getObjectTemplateAttributes(Vector vars) + { Vector res = new Vector(); + if (member != null && vars.contains(member.getName())) + { res.add(member.getName()); } + if (rest != null && vars.contains(rest.getName())) + { res.add(rest.getName()); } + return res; + } + + + public Vector objectTemplateAttributes() + { Vector res = new Vector(); + if (member != null && !(member.getName().equals("_"))) + { res.add(member); } + if (rest != null && !(rest.getName().equals("_"))) + { res.add(rest); } + return res; + } + + + public int complexity() + { int res = 0; + + if (member != null && !member.getName().equals("_")) + { res++; } + + if (rest != null && !rest.getName().equals("_")) + { res++; } + + if (where != null) + { res = res + where.syntacticComplexity(); } + return res; + } + + public int epl() + { int res = 0; + + if (member != null && !member.getName().equals("_")) + { res++; } + + if (rest != null && !rest.getName().equals("_")) + { res++; } + + /* for (int j = 0; j < members.size(); j++) + { Object m = members.get(j); + if (m instanceof Expression) + { Expression me = (Expression) m; + } + else + { TemplateExp te = (TemplateExp) m; + res += te.epl(); + } + } */ + + return res; + } + + public Vector operationsUsedIn() + { if (where != null) + { return where.allOperationsUsedIn(); } + return new Vector(); + } + + public String toString() + { String res = bindsTo + " : " + referredCollectionType + " { "; + + res = res + member + " ++ " + rest + " }"; + if (where != null) + { res = res + " { " + where + " }"; } + return res; + } // and { where } + +} + diff --git a/Compiler2.java b/Compiler2.java new file mode 100644 index 00000000..08f25576 --- /dev/null +++ b/Compiler2.java @@ -0,0 +1,6022 @@ +import java.io.*; +import java.util.Vector; +import java.util.StringTokenizer; +import javax.swing.JOptionPane; +import javax.swing.JTextArea; + +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ + +/* This is a parser for simple expressions involving =, =>, <=>, &, or. + For example: var1 = 5 & var2 = 6 => var3 = tty + No brackets are needed: => groups expressions first, then or then & + so att = val & att2 = val2 or ggh = val4 => val5 = val6 + is interpreted as + ((att = val & att2 = val2) or (ggh = val4)) => (val5 = val6) + + Modified to allow != (25.12.2000) + Modified to allow object references (7.4.2001) + Modified to allow <, >, etc (12.4.2002) + Modified to allow assignment := (21.4.2002) + Modified to allow +, - inside := and comparitors (4.5.2002) + Allow ":" (15.1.2003) + Allow "<:, intersect, union" (6.4.2003) + Added "*, /" and checkIfSetExpression (16.4.2003) + Introduced "|" and unspaced parsing (2.1.2006) + + package: Utilities +*/ + +public class Compiler2 +{ static final int INUNKNOWN = 0; + static final int INBASICEXP = 1; + static final int INSYMBOL = 2; + static final int INSTRING = 3; + + Vector lexicals; // of StringBuffer + Vector lexs = new Vector(); // of String + int[] bcount; // bracket count at this point in the lexical list + Vector ops = new Vector(); // of OpOccurrence + Expression finalexpression; + + + public boolean isStringDelimiter(char c) + { return (c == '"' || c == '`' || c == '\''); } + + /* This method breaks up a string into a sequence of strings, using + spaces as the break points: */ + + public void lexicalanalysis(String str) + { + boolean intoken = false; /* True if a token has been recognised */ + boolean instring = false; // true if within a string + + + int explen = str.length(); + lexicals = new Vector(); /* Sequence of lexicals */ + StringBuffer sb = null; /* Holds current lexical item */ + + char prev = ' '; + + for (int i = 0; i < explen; i++) + { char c = str.charAt(i); + + if (intoken) + { if (instring) + { if (isStringDelimiter(c) && prev != '\\') + { sb.append('"'); instring = false; + // intoken = false; + } + else + { sb.append(c); } + } + else // intoken, not instring + { if (isStringDelimiter(c)) + { instring = true; + // sb = new StringBuffer(); + // lexicals.addElement(sb); + sb.append('"'); + } + else if (c == ' ' || c == '\n' || c == '\t' || c == '\r') + { intoken = false; } + else + { sb.append(c); } + } + } + else // not intoken + { if (isStringDelimiter(c)) + { intoken = true; + instring = true; sb = new StringBuffer(); + lexicals.addElement(sb); sb.append('"'); + } + else if (c == ' ' || c == '\n' || c == '\t'|| c == '\r') + { intoken = false; } + else + { intoken = true; sb = new StringBuffer(); + lexicals.addElement(sb); sb.append(c); + } + } + prev = c; + } + + int llen = lexicals.size(); + bcount = new int[llen]; + int bnest = 0; + + for (int i = 0; i < llen; i++) + { StringBuffer sbb = (StringBuffer) lexicals.get(i); + lexs.add(sbb + ""); + bcount[i] = bnest; + if ("(".equals(sbb + "")) + { bnest++; } + else if (")".equals(sbb + "")) + { bnest--; } + else if (Expression.operators.contains(sbb + "")) + { + addToOps(new OpOccurrence(sbb + "",i,bnest)); + } + else if ("and".equals(sbb + "")) + { addToOps(new OpOccurrence("&",i,bnest)); + sbb = new StringBuffer("&"); + } + else if ("implies".equals(sbb + "")) + { addToOps(new OpOccurrence("=>",i,bnest)); + sbb = new StringBuffer("=>"); + } + } + System.out.println(ops); + } + + public int checkclones0() + { Vector clones = new Vector(); + int clonecount = 0; + for (int i = 0; i < lexicals.size() - 10; i++) + { String str = ""; + for (int j = i; j < i+10; j++) + { str = str + lexicals.get(j); } + if (clones.contains(str)) + { System.err.println("Clone: " + str + " at " + i); + clonecount++; + } + else + { clones.add(str); } + } + return clonecount; + } + + public int checkclones(Vector types, Vector entities) + { Vector clones = new Vector(); + + int clonecount = 0; + + for (int i = 0; i < lexicals.size() - 10; i++) + { boolean match = true; + int j = i + 11; + int k = 0; + String str = ""; + + while (j + k < lexicals.size() && i + k < j && match) + { String stri = "" + lexicals.get(i+k); + String strj = "" + lexicals.get(j+k); + if (stri.equals(strj)) + { k++; + str = str + " " + stri; + } + else + { match = false; + if (k > 10) + { Expression e = parse_ATLexpression(0,i,i+k-1,entities,types); + if (e != null) + { clones.add(">>CLONE at " + i + "," + j + " SIZE= " + k + ">> " + str); + clonecount++; + } + } + j = j + k + 1; + k = 0; + str = ""; + match = true; + } + } + + if (match && k > 10) + { clones.add(">>CLONE at " + i + "," + j + " SIZE= " + k + ">> " + str); + clonecount++; + } + } + + System.out.println(clones); + return clonecount; + } + + private void addToOps(OpOccurrence oc) + { // Orders ocs by bcount, then by op priority, then by position + // if (ops.size() == 0) + // { ops.add(oc); + // return; + // } + System.out.println(oc); + + for (int i = 0; i < ops.size(); i++) + { OpOccurrence best = (OpOccurrence) ops.get(i); + if (oc.bcount < best.bcount) + { ops.add(i,oc); + return; + } + if (oc.bcount == best.bcount && + oc.priority() < best.priority()) + { ops.add(i,oc); + return; + } + if (oc.bcount == best.bcount && oc.op.equals(best.op) && + oc.location < best.location) + { ops.add(i,oc); + return; + } + } + ops.add(oc); + } + + private OpOccurrence getBestOcc(int st, int en) + { OpOccurrence res = null; + for (int i = 0; i < ops.size(); i++) + { OpOccurrence op = (OpOccurrence) ops.get(i); + if (op.location >= st && op.location <= en) + { return op; } + } + return res; + } + + private int getBestOpOccurrence(String op, int st, int en) + { int pri = lexs.size() + 1; + int best = en + 1; + + for (int i = st; i < en; i++) + { String pp = (String) lexs.get(i); + if (op.equals(pp)) + { if (bcount[i] < pri) + { best = i; + pri = bcount[i]; + } + } + } + return best; + } + + private int getBestAndOpOccurrence(int st, int en) + { int pri = lexs.size() + 1; + int best = en + 1; + for (int i = st; i < en; i++) + { String pp = (String) lexs.get(i); + if ("&".equals(pp)) + { if (bcount[i] < pri) + { best = i; + pri = bcount[i]; + } + } + } + return best; + } + + /* if (str.charAt(i) == ' ' || str.charAt(i) == '\n') + { + if (intoken) { intoken = false; } + } + else + { + if (intoken == false) + { + intoken = true; + sb = new StringBuffer(); + lexicals.addElement(sb); + } + sb.append(str.charAt(i)); + } + } + } */ + + public boolean isValidOCLOperator(String str) + { if (str.equals("exists") || str.equals("existsLC") || str.equals("exists1") || + str.equals("forAll") || str.equals("allInstances") || + str.equals("select") || str.equals("collect") || str.equals("reject") || + str.equals("includes") || str.equals("including") || str.equals("excludes") || + str.equals("excluding") || str.equals("intersection") || str.equals("union") || + str.equals("unionAll") || str.equals("intersectAll") || str.equals("at") || + str.equals("selectMaximals") || str.equals("selectMinimals") || str.equals("not") || + str.equals("any") || str.equals("size") || str.equals("last") || + str.equals("first") || str.equals("includesAll") || str.equals("excludesAll") || + str.equals("append") || str.equals("prepend") || str.equals("min") || + str.equals("max") || str.equals("sum") || str.equals("display") || + str.equals("before") || str.equals("after") || str.equals("xor") || + str.equals("toLowerCase") || str.equals("toUpperCase") || str.equals("Sum") || + str.equals("Prd") || str.equals("symmetricDifference") || str.equals("oclIsUndefined") || + str.equals("reverse") || str.equals("sort") || str.equals("subcollections") || + str.equals("front") || str.equals("tail") || str.equals("insertAt") || + str.equals("subrange") || str.equals("characters") || str.equals("isLong") || + str.equals("closure") || str.equals("asSet") || str.equals("asSequence") || + str.equals("sqr") || str.equals("floor") || str.equals("ceil") || + str.equals("round") || str.equals("exp") || str.equals("pow") || + str.equals("sin") || str.equals("cos") || str.equals("tan") || str.equals("toLong") || + str.equals("asin") || str.equals("acos") || str.equals("atan") || + str.equals("sinh") || str.equals("cosh") || str.equals("tanh") || + str.equals("log10") || str.equals("cbrt") || str.equals("isInteger") || + str.equals("toInteger") || str.equals("isReal") || str.equals("toReal") || + str.equals("log") || str.equals("count") || str.equals("hasPrefix") || + str.equals("hasSuffix") || str.equals("isEmpty") || str.equals("notEmpty") || + str.equals("isUnique") || str.equals("prd") || str.equals("sortedBy") || + str.equals("sqrt") || str.equals("abs") || "flatten".equals(str) || + str.equals("oclAsType") || str.equals("oclIsKindOf") || str.equals("or") || + str.equals("indexOf") || str.equals("isDeleted") || str.equals("iterate")) + { return true; } + return false; + } + + public boolean checkSyntax(Entity context, Vector entities, + Vector varsymbs, Vector messages) + { Vector variables = new Vector(); + Vector openBrackets = new Vector(); + for (int i = 0; i < lexicals.size(); i++) + { String tok = lexicals.get(i) + ""; + if ("(".equals(tok)) + { openBrackets.add(0, new Integer(i)); } + else if (")".equals(tok)) + { if (openBrackets.size() > 0) + { openBrackets.remove(0); } + else + { messages.add("Unmatched ) at token " + i); + JOptionPane.showMessageDialog(null, "Unmatched ) at token " + i, "Syntax error", JOptionPane.ERROR_MESSAGE); + return false; + } + } + else if ("->".equals(tok)) + { if (i + 1 < lexicals.size()) + { if (isValidOCLOperator(lexicals.get(i+1) + "")) + { i++; } + else + { messages.add("Unrecognised OCL operator: " + lexicals.get(i+1) + " after ->"); + JOptionPane.showMessageDialog(null, "Unrecognised OCL operator: " + lexicals.get(i+1) + " after ->", "Syntax error", JOptionPane.ERROR_MESSAGE); + return false; + } + } + else + { messages.add("Invalid syntax: -> at end of expression"); + JOptionPane.showMessageDialog(null, "Invalid syntax: -> at end of expression", "Syntax error", JOptionPane.ERROR_MESSAGE); + return false; + } + } + else + { boolean res = validIdentifierOrOperator(i,tok,context,entities,varsymbs,variables,messages); + if (res == false) { return res; } + } + } + if (openBrackets.size() > 0) + { messages.add("Unmatched brackets at positions " + openBrackets); + JOptionPane.showMessageDialog(null, "Unmatched brackets at positions " + openBrackets, + "Syntax error", JOptionPane.ERROR_MESSAGE); + return false; + } + return true; + } + + public boolean validIdentifierOrOperator(int i, String tok, Entity context, + Vector entities, Vector varsymbs, + Vector variables, Vector messages) + { if (Expression.alloperators.contains(tok) || "[".equals(tok) || "]".equals(tok) || + "{".equals(tok) || "}".equals(tok) || "Set{".equals(tok) || "Sequence{".equals(tok) || + "Set".equals(tok) || "Sequence".equals(tok) || "Integer".equals(tok) || + "|".equals(tok) || ",".equals(tok)) + { return true; } + ModelElement me = ModelElement.lookupByName(tok,entities); + if (me != null) { return true; } + if (Expression.isValue(tok)) + { return true; } + if (Expression.isSet(tok) || Expression.isSequence(tok)) + { return true; } + int dotind = tok.indexOf("."); + if (dotind == -1) + { return validIdentifier(i,tok,context,varsymbs,variables,entities,messages); } + StringTokenizer st = new StringTokenizer(tok, "."); + while (st.hasMoreTokens()) + { String str = st.nextToken(); + return validIdentifier(i,str,context,varsymbs,variables,entities,messages); + } + return true; + } + + public boolean validIdentifier(int i, String tok, Entity context, + Vector varsymbs, Vector variables, Vector entities, Vector messages) + { String str = tok; + int atind = tok.indexOf("@"); + if (atind >= 0) + { str = tok.substring(0,atind); } + if (variables.contains(str) || "Integer".equals(str) || str.equals("Real")) + { return true; } + if (context != null && context.hasFeatureOrOperation(str)) + { return true; } + if (isKeyword(str)) + { messages.add("Error: " + str + " invalid identifier (keyword)"); + JOptionPane.showMessageDialog(null, "Error: " + str + " invalid identifier (keyword)", + "Syntax error", JOptionPane.ERROR_MESSAGE); + return false; + } + if (invalidLexical(str)) + { messages.add("Error: " + str + " invalid lexical"); + JOptionPane.showMessageDialog(null, "Error: " + str + " invalid lexical", + "Syntax error", JOptionPane.ERROR_MESSAGE); + return false; + } + // also if contains "_" + if ("self".equals(str) && context != null) { } + else if (i < lexicals.size() - 1 && varsymbs.contains(lexicals.get(i+1) + "") ) + { JOptionPane.showMessageDialog(null, str + " is a variable", + "Syntax check", JOptionPane.INFORMATION_MESSAGE); + variables.add(str); + } + else + { ModelElement me = ModelElement.lookupByName(str,entities); + if (me != null) { return true; } + else + { messages.add("Warning: " + str + " not entity or feature of context class: " + context); + /* JOptionPane.showMessageDialog(null, "Warning: " + str + + " not feature of context class: " + context, + "Syntax issue", JOptionPane.WARNING_MESSAGE); */ + } + } + return true; + } + + public boolean invalidLexical(String str) + { if ("%".equals(str) || "_".equals(str) || "?".equals(str) || "~".equals(str) ) + { return true; } + return false; + } + + public boolean invalidBasicExp(String str) + { if ("(".equals(str) || ")".equals(str) || "[".equals(str) || "]".equals(str) || + "{".equals(str) || "}".equals(str) || Expression.alloperators.contains(str) || + ",".equals(str) || + "%".equals(str) || "_".equals(str) || "?".equals(str) || "~".equals(str) ) + { return true; } + return false; + } + + + public boolean isKeyword(String str) + { if (str.equals("class") || str.equals("if") || str.equals("while") || + str.equals("return") || str.equals("break") || str.equals("continue") || + str.equals("float") || str.equals("char") || str.equals("byte") || + // str.equals("boolean") || str.equals("int") || + // str.equals("long") || str.equals("double") || + str.equals("transient") || str.equals("volatile") || str.equals("short") || + str.equals("native") || str.equals("enum") || str.equals("package") || + str.equals("strictfp") || str.equals("wait") || str.equals("goto") || + str.equals("const") || str.equals("notify") || str.equals("notifyAll") || + str.equals("case") || str.equals("switch") || str.equals("this") || str.equals("null") || + str.equals("new") || str.equals("try") || str.equals("catch") || str.equals("finally") || + str.equals("synchronized") || str.equals("until") || str.equals("do") || + str.equals("interface") || str.equals("extends") || str.equals("implements") || + str.equals("for") || str.equals("instanceof") || str.equals("private") || + str.equals("public") || str.equals("final") || str.equals("static") || + str.equals("void") || str.equals("abstract") || str.equals("protected") || + str.equals("else") || str.equals("throw") || str.equals("throws")) + { return true; } // Java keywords. "super" is allowed. + return false; + } + + private static boolean isIdentifier(String s) + { boolean res = true; + if (Character.isDigit(s.charAt(0))) { return false; } + + for (int i = 0; i < s.length(); i++) + { if (Character.isLetterOrDigit(s.charAt(i)) || + s.charAt(i) == '!' || s.charAt(i) == '@') { } + else + { return false; } + } + return res; + } // does not permit ! inside strings, or _ + + private static boolean isATLIdentifier(String s) + { boolean res = true; + if (Character.isLetter(s.charAt(0)) || s.charAt(0) == '#') + { } else { return false; } + + for (int i = 1; i < s.length(); i++) + { if (Character.isLetterOrDigit(s.charAt(i)) || s.charAt(i) == '!') { } + else + { return false; } + } + return res; + } + + private Vector identifierSequence(int st, int en) + { if (st > en) { return null; } // or empty sequence? + + Vector res = new Vector(); + for (int i = st; i < en; i++) + { String ss = lexicals.get(i) + ""; + if (isIdentifier(ss)) + { BasicExpression ee = new BasicExpression(ss,0); + res.add(ee.checkIfSetExpression()); + } + else if (",".equals(ss)) { } + else { return null; } + } + + String last = lexicals.get(en) + ""; + if (isIdentifier(last)) + { BasicExpression ee = new BasicExpression(last,0); + res.add(ee.checkIfSetExpression()); + } + + return res; + } + + private static boolean isBasicExpCharacter(char c) + { return (Character.isLetterOrDigit(c) || c == '.' || c == '$' || c == '@'); } + + private static boolean isATLBasicExpCharacter(char c) + { return (Character.isLetterOrDigit(c) || c == '.' || c == '#' || c == '!' || c == '_'); } + + private static boolean isSymbolCharacter(char c) + { return (c == '<' || c == '>' || c == '=' || c == '*' || c == '/' || c == '\\' || + c == '-' || c == ',' || c == ';' || c == '!' || + c == '+' || c == '&' || c == '^' || c == ':' || c == '|' || + c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || + c == ']' || c == '#'); + } // c == '\'' || + // why include single quote? It should not be used. + + + private static boolean isXMLSymbolCharacter(char c) + { return (c == '<' || c == '>' || c == '=' || c == '*' || c == '/' || c == '\\' || + c == '-' || c == ',' || c == '\'' || c == '?' || + c == '+' || c == '&' || c == '^' || c == '|' || + c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || + c == ']' || c == '#'); + } + // { return (c == '<' || c == '>' || c == '='); } + + private static boolean isXMLBasicExpCharacter(char c) + { return (Character.isLetterOrDigit(c) || c == '.' || c == '$' || c == '@' || c == ':'); } + + + public void nospacelexicalanalysis(String str) + { int in = INUNKNOWN; + char previous = ' '; + + int explen = str.length(); + lexicals = new Vector(explen); /* Sequence of lexicals */ + StringBuffer sb = null; /* Holds current lexical item */ + + char prev = ' '; + + for (int i = 0; i < explen; i++) + { char c = str.charAt(i); + if (in == INUNKNOWN) + { if (isSymbolCharacter(c)) + { sb = new StringBuffer(); // start new buffer for the symbol + lexicals.addElement(sb); + in = INSYMBOL; + sb.append(c); + previous = c; + } + else if (isBasicExpCharacter(c)) + { sb = new StringBuffer(); // start new buffer for the expression + lexicals.addElement(sb); + in = INBASICEXP; + sb.append(c); + } + else if (isStringDelimiter(c)) + { sb = new StringBuffer(); // start new buffer for the string + lexicals.addElement(sb); + in = INSTRING; + sb.append('"'); + } + else if (c == ' ' || c == '\n' || c == '\t' || c == '\r') + { } + else + { sb = new StringBuffer(); // unrecognised lexical + lexicals.addElement(sb); + sb.append(c); + if (c == '_') + { // System.out.println("Metavariable symbol: " + c); + in = INBASICEXP; + } + else + { System.err.println("Unrecognised literal: " + c); } + } + } + else if (in == INBASICEXP) + { if (isBasicExpCharacter(c) || c == '"') // Why allow " in a basic exp??? + { sb.append(c); } // carry on adding to current basic exp + else if (c == '_') + { // System.out.println("Metavariable symbol: " + c); + sb.append(c); + } + else if (isSymbolCharacter(c)) + { sb = new StringBuffer(); // start new buffer for the symbol + lexicals.addElement(sb); + in = INSYMBOL; + sb.append(c); + previous = c; + } + else if (c == ' ' || c == '\n' || c == '\t' || c == '\r') + { in = INUNKNOWN; } + else + { sb = new StringBuffer(); // unrecognised lexical + lexicals.addElement(sb); + in = INUNKNOWN; + System.err.println("Unrecognised literal in expression: " + c); + sb.append(c); + } + } + else if (in == INSYMBOL) + { if (isStringDelimiter(c)) + { sb = new StringBuffer(); // start new buffer for the string + lexicals.addElement(sb); + in = INSTRING; + sb.append('"'); + } + else if (c == '(' || c == ')') + { sb = new StringBuffer(); // start new buffer for the new symbol + lexicals.addElement(sb); + in = INSYMBOL; + previous = c; + sb.append(c); + } + else if (c == '_') + { // System.out.println("Metavariable symbol: " + c); + sb = new StringBuffer(); // start new buffer for the string + lexicals.addElement(sb); + in = INBASICEXP; + sb.append(c); + } + else if (isBasicExpCharacter(c)) + { sb = new StringBuffer(); // start new buffer for basic exp + lexicals.addElement(sb); + in = INBASICEXP; + sb.append(c); + } + else if (isSymbolCharacter(c)) + { if (validFollowingCharacter(previous,c)) + { sb.append(c); } + else + { sb = new StringBuffer(); // start new buffer for the new symbol + lexicals.addElement(sb); + in = INSYMBOL; + sb.append(c); + } + previous = c; + } + else if (c == ' ' || c == '\n' || c == '\t' || c == '\r') + { in = INUNKNOWN; } + } + else if (in == INSTRING) + { if (isStringDelimiter(c) && prev != '\\') /* end of string */ + { sb.append('"'); + in = INUNKNOWN; + } + else + { sb.append(c); } + } + previous = c; + prev = c; + } + + int llen = lexicals.size(); + bcount = new int[llen]; + int bnest = 0; + + for (int i = 0; i < llen; i++) + { StringBuffer sbb = (StringBuffer) lexicals.get(i); + lexs.add(sbb + ""); + bcount[i] = bnest; + if ("(".equals(sbb + "")) + { bnest++; } + else if (")".equals(sbb + "")) + { bnest--; } + else if (Expression.operators.contains(sbb + "")) + { + addToOps(new OpOccurrence(sbb + "",i,bnest)); + } + else if ("and".equals(sbb + "")) + { addToOps(new OpOccurrence("&",i,bnest)); + sbb = new StringBuffer("&"); + } + else if ("implies".equals(sbb + "")) + { addToOps(new OpOccurrence("=>",i,bnest)); + sbb = new StringBuffer("=>"); + } + } + // System.out.println(ops); + } + + // Updated (November 2012) to handle XML: + + public void nospacelexicalanalysisxml(String str) + { int in = INUNKNOWN; + char previous = ' '; + + int explen = str.length(); + lexicals = new Vector(explen); /* Sequence of lexicals */ + StringBuffer sb = null; /* Holds current lexical item */ + + for (int i = 0; i < explen; i++) + { char c = str.charAt(i); + if (in == INUNKNOWN) + { if (isXMLSymbolCharacter(c)) + { sb = new StringBuffer(); // start new buffer for the symbol + lexicals.addElement(sb); + in = INSYMBOL; + sb.append(c); + previous = c; + } + else if (isXMLBasicExpCharacter(c)) + { sb = new StringBuffer(); // start new buffer for the expression + lexicals.addElement(sb); + in = INBASICEXP; + sb.append(c); + } + else if (c == '"') + { sb = new StringBuffer(); // start new buffer for the string + lexicals.addElement(sb); + in = INSTRING; + sb.append(c); + } + else if (c == ' ' || c == '\n' || c == '\t' || c == '\r') + { } + else + { sb = new StringBuffer(); // unrecognised lexical + lexicals.addElement(sb); + System.err.println("Unrecognised literal: " + c); + sb.append(c); + } + } + else if (in == INBASICEXP) + { if (isXMLBasicExpCharacter(c) || c == '"') + { sb.append(c); } // carry on adding to current basic exp + else if (isXMLSymbolCharacter(c)) + { sb = new StringBuffer(); // start new buffer for the symbol + lexicals.addElement(sb); + in = INSYMBOL; + sb.append(c); + previous = c; + } + else if (c == ' ' || c == '\n' || c == '\t' || c == '\r') + { in = INUNKNOWN; } + else + { sb = new StringBuffer(); // unrecognised lexical + lexicals.addElement(sb); + in = INUNKNOWN; + System.err.println("Unrecognised literal in expression: " + c); + sb.append(c); + } + } + else if (in == INSYMBOL) + { if (c == '"') + { sb = new StringBuffer(); // start new buffer for the string + lexicals.addElement(sb); + in = INSTRING; + sb.append(c); + } + else if (c == '(' || c == ')') + { sb = new StringBuffer(); // start new buffer for the new symbol + lexicals.addElement(sb); + in = INSYMBOL; + previous = c; + sb.append(c); + } + else if (isXMLBasicExpCharacter(c)) + { sb = new StringBuffer(); // start new buffer for basic exp + lexicals.addElement(sb); + in = INBASICEXP; + sb.append(c); + } + else if (isXMLSymbolCharacter(c)) + { if (validFollowingCharacterXML(previous,c)) + { sb.append(c); } + else + { sb = new StringBuffer(); // start new buffer for the new symbol + lexicals.addElement(sb); + in = INSYMBOL; + sb.append(c); + } + previous = c; + } + else if (c == ' ' || c == '\n' || c == '\t' || c == '\r') + { in = INUNKNOWN; } + } + else if (in == INSTRING) + { if (c == '"') /* end of string */ + { sb.append(c); + in = INUNKNOWN; + } + else + { sb.append(c); } + } + previous = c; + } + } + + private static boolean validFollowingCharacter(char c1, char c2) + { if (c1 == '<') + { if (c2 == '=' || c2 == ':' || c2 == '>') // final case for ATL, treated as /= + { return true; } /* /<: should be ok, but not ') + { if (c2 == '=') { return true; } + return false; + } + if (c1 == '/') + { if (c2 == '=' || c2 == ':' || c2 == '\\' || c2 == '<') { return true; } + return false; + } + if (c1 == '\\') + { if (c2 == '/') { return true; } + return false; + } + if (c1 == '=') + { if (c2 == '>') { return true; } + return false; + } + if (c1 == '-') + { if (c2 == '>') { return true; } + return false; + } + if (c1 == ':') + { if (c2 == '=') { return true; } + return false; + } + return false; + } + + private static boolean validFollowingCharacterXML(char c1, char c2) + { if (c1 == '<') + { if (c2 == '=' || c2 == ':' || c2 == '/') + { return true; } + return false; + } + if (c1 == '>') + { if (c2 == '=') { return true; } + return false; + } + if (c1 == '/') + { if (c2 == '=' || c2 == ':' || c2 == '\\' || c2 == '>') { return true; } + return false; + } + if (c1 == '\\') + { if (c2 == '/') { return true; } + return false; + } + if (c1 == '=') + { if (c2 == '>') { return true; } + return false; + } + if (c1 == '-') + { if (c2 == '>') { return true; } + return false; + } + if (c1 == ':') + { if (c2 == '=') { return true; } + return false; + } + return false; + } + + + + + public void displaylexs() + { + for (int i = 0; i < lexicals.size(); i++) + { + System.out.println(((StringBuffer) lexicals.elementAt(i)).toString()); + } + } + + public void displaylexs(int a, int b) + { + for (int i = a; i < lexicals.size() & i <= b; i++) + { + System.out.println(((StringBuffer) lexicals.elementAt(i)).toString()); + } + } + + public Type parseType() + { int en = lexicals.size(); + return parseType(0, en-1, new Vector(), new Vector()); + } + + public Type parseType(Vector entities, Vector types) + { int en = lexicals.size(); + return parseType(0,en-1,entities,types); + } + + public Type parseType(int st, int en, Vector entities, Vector types) + { if (st > en) { return null; } + String typ = lexicals.get(st) + ""; + if (st == en && + ("int".equals(typ) || "long".equals(typ) || typ.equals("String") || + "Integer".equals(typ) || "Real".equals(typ) || typ.equals("Boolean") || + "void".equals(typ) || typ.equals("double") || typ.equals("boolean") || + typ.startsWith("_"))) + { System.out.println("Creating new basic type " + typ); + return new Type(typ,null); + } + else if ("Map".equals(typ)) // for ATL + { Type tt = null; + for (int i = st + 2; i < en; i++) + { String ss = lexicals.get(i) + ""; + if (ss.equals(",")) + { Type t1 = parseType(st+2,i-1,entities,types); + Type t2 = parseType(i+1,en-1,entities,types); + if (t1 != null && t2 != null) + { tt = new Type("Map",t1,t2); + tt.setKeyType(t1); + tt.setElementType(t2); + return tt; + } + } + } + if (tt == null) + { System.err.println("******** Invalid map type: " + showLexicals(st,en)); + return null; + } + else + { return tt; } + } + else if (typ.equals("Set") || typ.equals("Sequence")) + { Type tt = new Type(typ,null); + Type et = parseType(st + 2, en - 1, entities, types); + if (et != null && tt != null) + { tt.setElementType(et); } + return tt; + } + else + { Entity ee = (Entity) ModelElement.lookupByName(typ,entities); + if (ee != null) + { return new Type(ee); } + else + { return (Type) ModelElement.lookupByName(typ,types); } + } + } // also need OrderedSet, Bag, Tuple for ATL. + + public Sbvrse parseSbvrse(int st, int en) + { if (st > en) { return null; } + if (lexicals.size() < 10) { return null; } + Sbvrse sbvrse = new Sbvrse(); + + String st1 = lexicals.get(0) + ""; + String st2 = lexicals.get(1) + ""; + String st3 = lexicals.get(2) + ""; + String st4 = lexicals.get(3) + ""; + String st5 = lexicals.get(4) + ""; + if (("It".equals(st1) || "it".equals(st1)) && "is".equals(st2) && + "necessary".equals(st3) && "that".equals(st4) && "each".equals(st5)) + { String definedTerm = ""; + int i = 5; + for ( ; i < lexicals.size(); i++) + { String str = lexicals.get(i) + ""; + if ("instance".equals(str)) + { // text between 5 and i-1 is a defined term + sbvrse.setDefinedTerm(definedTerm); + break; + } + else + { definedTerm = definedTerm + str; } + } + + if (i+9 < lexicals.size()) + { String idsource = lexicals.get(i+1) + ""; + sbvrse.setSourceInstance(idsource); + String st6 = lexicals.get(i+2) + ""; // maps + String st7 = lexicals.get(i+3) + ""; // to + String st8 = lexicals.get(i+4) + ""; // a or an + String ttype = lexicals.get(i+5) + ""; + sbvrse.setTargetType(ttype); + String tid = lexicals.get(i+7) + ""; + sbvrse.setTargetInstance(tid); + Expression exp1 = parse_expression(0, i+10, en); + sbvrse.setSuccedent(exp1); + } + } + return sbvrse; + } + + public Sbvrse parseSbvrse() + { int en1 = lexicals.size()-1; + for (int i = 0; i < lexicals.size(); i++) + { String lex = lexicals.get(i) + ""; + if (";".equals(lex.trim())) + { System.out.println("+++++++++++"); + Sbvrse res = parseSbvrse(0,i-1); + parseSbvrse2(res,i+1,en1); + return res; + } + } + return parseSbvrse(0,en1); + } + + public void parseSbvrse2(Sbvrse sb, int st, int en) + { if (st > en) { return; } + + if ("Each".equals(lexicals.get(st) + "") && st + 5 < en) + { String srcType = lexicals.get(st+1) + ""; + sb.setSourceType(srcType); + String st2 = lexicals.get(st + 2) + ""; + String st3 = lexicals.get(st + 3) + ""; + String st4 = lexicals.get(st + 4) + ""; + String st5 = lexicals.get(st + 5) + ""; + if ("is".equals(st2) && "considered".equals(st3) && + "to".equals(st4) && "be".equals(st5)) + { String definedTerm = ""; + int i = st + 6; + for ( ; i < lexicals.size(); i++) + { String str = lexicals.get(i) + ""; + if ("if".equals(str)) + { // text between st + 6 and i-1 is the defined term + // sbvrse.setDefinedTerm(definedTerm); + break; + } + else + { definedTerm = definedTerm + str; } + } + + if (i+2 < lexicals.size()) + { String st7 = lexicals.get(i+1) + ""; // it + String st8 = lexicals.get(i+2) + ""; // has + Expression exp1 = parse_expression(0, i+3, en); + sb.setCondition(exp1); + } + } + } + } // should pair up the defined terms uses and definitions. + + public Expression parse(JTextArea messageArea) + { messageArea.append("LEXICALS: " + lexicals + "\n\r"); + Expression ee = parse_expression(0,0,lexicals.size()-1); + finalexpression = ee; + if (ee == null) + { messageArea.append("Not a valid OCL constraint. Trying to parse as an operation.\n\r"); } + else + { messageArea.append("This is a valid OCL expression for a constraint.\n\r"); } + return ee; + } + + public CGRule parse_ExpressionCodegenerationrule(String rule) + { String buff = ""; + for (int i = 0; i < rule.length(); i++) + { char c = rule.charAt(i); + if (c == '|' && i + 2 < rule.length() && rule.charAt(i+1) == '-' && + rule.charAt(i+2) == '-' && rule.charAt(i+3) == '>') + { String lhs = rule.substring(0,i); + nospacelexicalanalysis(lhs); + Expression lhsexp = parseExpression(); + + if (lhsexp != null) + { String rhs = rule.substring(i+4,rule.length()); + for (int j = 0; j < rhs.length(); j++) + { char d = rhs.charAt(j); + if (d == '<' && j+5 < rhs.length() && + rhs.charAt(j+1) == 'w' && + rhs.charAt(j+2) == 'h' && + rhs.charAt(j+3) == 'e' && + rhs.charAt(j+4) == 'n' && + rhs.charAt(j+5) == '>') + { String conditions = rhs.substring(j+6,rhs.length()); + Vector conds = parseCGconditions(conditions); + String rhstext = rhs.substring(0,j); + CGRule r = new CGRule(lhsexp,rhstext,conds); + return r; + } + } + CGRule res = new CGRule(lhsexp,rhs); + return res; + } + } + } + System.err.println(">>> Invalid rule: " + rule); + return null; + } + + public CGRule parse_StatementCodegenerationrule(String rule, Vector entities, Vector types) + { String buff = ""; + for (int i = 0; i < rule.length(); i++) + { char c = rule.charAt(i); + if (c == '|' && i + 2 < rule.length() && rule.charAt(i+1) == '-' && + rule.charAt(i+2) == '-' && rule.charAt(i+3) == '>') + { String lhs = rule.substring(0,i); + nospacelexicalanalysis(lhs); + // Statement lhsexp = parseStatement(entities,types); + Vector variables = new Vector(); + for (int k = 0; k < lexicals.size(); k++) + { String lex = lexicals.get(k) + ""; + if (lex.startsWith("_")) + { variables.add(lex); } + } + + System.out.println("LHS variables = " + variables); + + if (lhs != null) + { String rhs = rule.substring(i+4,rule.length()); + for (int j = 0; j < rhs.length(); j++) + { char d = rhs.charAt(j); + if (d == '<' && j+5 < rhs.length() && + rhs.charAt(j+1) == 'w' && + rhs.charAt(j+2) == 'h' && + rhs.charAt(j+3) == 'e' && + rhs.charAt(j+4) == 'n' && + rhs.charAt(j+5) == '>') + { String conditions = rhs.substring(j+6,rhs.length()); + Vector conds = parseCGconditions(conditions); + String rhstext = rhs.substring(0,j); + CGRule r = new CGRule(lhs,rhstext,variables,conds); + // CGRule r = new CGRule(lhsexp,rhstext,conds); + return r; + } + } + // CGRule res = new CGRule(lhsexp,rhs); + CGRule res = new CGRule(lhs,rhs,variables,new Vector()); + return res; + } + } + } + System.err.println(">>> Invalid rule: " + rule); + return null; + } + + public CGRule parse_UseCaseCodegenerationrule(String rule, Vector entities, Vector types) + { String buff = ""; + for (int i = 0; i < rule.length(); i++) + { char c = rule.charAt(i); + if (c == '|' && i + 2 < rule.length() && rule.charAt(i+1) == '-' && + rule.charAt(i+2) == '-' && rule.charAt(i+3) == '>') + { String lhs = rule.substring(0,i); + nospacelexicalanalysis(lhs); + // Statement lhsexp = parseStatement(entities,types); + Vector variables = new Vector(); + for (int k = 0; k < lexicals.size(); k++) + { String lex = lexicals.get(k) + ""; + if (lex.startsWith("_")) + { variables.add(lex); } + } + + System.out.println("LHS variables = " + variables); + + if (lhs != null) + { String rhs = rule.substring(i+4,rule.length()); + for (int j = 0; j < rhs.length(); j++) + { char d = rhs.charAt(j); + if (d == '<' && j+5 < rhs.length() && + rhs.charAt(j+1) == 'w' && + rhs.charAt(j+2) == 'h' && + rhs.charAt(j+3) == 'e' && + rhs.charAt(j+4) == 'n' && + rhs.charAt(j+5) == '>') + { String conditions = rhs.substring(j+6,rhs.length()); + Vector conds = parseCGconditions(conditions); + String rhstext = rhs.substring(0,j); + CGRule r = new CGRule(lhs,rhstext,variables,conds); + // CGRule r = new CGRule(lhsexp,rhstext,conds); + return r; + } + } + // CGRule res = new CGRule(lhsexp,rhs); + CGRule res = new CGRule(lhs,rhs,variables,new Vector()); + return res; + } + } + } + System.err.println(">>> Invalid rule: " + rule); + return null; + } + + public CGRule parse_TypeCodegenerationrule(String rule) + { String buff = ""; + for (int i = 0; i < rule.length(); i++) + { char c = rule.charAt(i); + if (c == '|' && i + 2 < rule.length() && rule.charAt(i+1) == '-' && + rule.charAt(i+2) == '-' && rule.charAt(i+3) == '>') + { String lhs = rule.substring(0,i); + nospacelexicalanalysis(lhs); + Type lhsexp = parseType(new Vector(),new Vector()); + System.out.println("LHS of type rule = " + lhsexp); + + if (lhsexp != null) + { String rhs = rule.substring(i+4,rule.length()); + for (int j = 0; j < rhs.length(); j++) + { char d = rhs.charAt(j); + if (d == '<' && j+5 < rhs.length() && + rhs.charAt(j+1) == 'w' && + rhs.charAt(j+2) == 'h' && + rhs.charAt(j+3) == 'e' && + rhs.charAt(j+4) == 'n' && + rhs.charAt(j+5) == '>') + { String conditions = rhs.substring(j+6,rhs.length()); + Vector conds = parseCGconditions(conditions); + String rhstext = rhs.substring(0,j); + CGRule r = new CGRule(lhsexp,rhstext,conds); + return r; + } + } + CGRule res = new CGRule(lhsexp,rhs); + System.out.println("Variables of rule " + res + " are: " + res.variables); + return res; + } + } + } + System.err.println(">>> Invalid rule: " + rule); + return null; + } + + public CGRule parse_EntityCodegenerationrule(String rule) + { String buff = ""; + for (int i = 0; i < rule.length(); i++) + { char c = rule.charAt(i); + if (c == '|' && i + 2 < rule.length() && rule.charAt(i+1) == '-' && + rule.charAt(i+2) == '-' && rule.charAt(i+3) == '>') + { String lhs = rule.substring(0,i); + nospacelexicalanalysis(lhs); + + Vector variables = new Vector(); + for (int k = 0; k < lexicals.size(); k++) + { String lex = lexicals.get(k) + ""; + if (lex.startsWith("_")) + { variables.add(lex); } + } + + // System.out.println("LHS variables = " + variables); + + if (lhs != null) + { String rhs = rule.substring(i+4,rule.length()); + for (int j = 0; j < rhs.length(); j++) + { char d = rhs.charAt(j); + if (d == '<' && j+5 < rhs.length() && + rhs.charAt(j+1) == 'w' && + rhs.charAt(j+2) == 'h' && + rhs.charAt(j+3) == 'e' && + rhs.charAt(j+4) == 'n' && + rhs.charAt(j+5) == '>') + { String conditions = rhs.substring(j+6,rhs.length()); + Vector conds = parseCGconditions(conditions); + String rhstext = rhs.substring(0,j); + CGRule r = new CGRule(lhs,rhstext,variables,conds); + return r; + } + } + CGRule res = new CGRule(lhs,rhs,variables,new Vector()); + return res; + } + } + } + System.err.println(">>> Invalid rule: " + rule); + return null; + } + + public CGRule parse_TextCodegenerationrule(String rule) + { String buff = ""; + for (int i = 0; i < rule.length(); i++) + { char c = rule.charAt(i); + if (c == '|' && i + 2 < rule.length() && rule.charAt(i+1) == '-' && + rule.charAt(i+2) == '-' && rule.charAt(i+3) == '>') + { String lhs = rule.substring(0,i); + + Vector variables = new Vector(); + for (int k = 0; k + 1 < lhs.length(); k++) + { char lex = lhs.charAt(k); + if (lex == '_') + { variables.add("_" + lhs.charAt(k+1)); } + } + + // System.out.println("LHS variables = " + variables); + + if (lhs != null) + { String rhs = rule.substring(i+4,rule.length()); + for (int j = 0; j < rhs.length(); j++) + { char d = rhs.charAt(j); + if (d == '<' && j+5 < rhs.length() && + rhs.charAt(j+1) == 'w' && + rhs.charAt(j+2) == 'h' && + rhs.charAt(j+3) == 'e' && + rhs.charAt(j+4) == 'n' && + rhs.charAt(j+5) == '>') + { String conditions = rhs.substring(j+6,rhs.length()); + Vector conds = parseCGconditions(conditions); + String rhstext = rhs.substring(0,j); + CGRule r = new CGRule(lhs,rhstext,variables,conds); + return r; + } + } + CGRule res = new CGRule(lhs,rhs,variables,new Vector()); + return res; + } + } + } + System.err.println(">>> Invalid rule: " + rule); + return null; + } + + public CGRule parse_AttributeCodegenerationrule(String rule) + { String buff = ""; + for (int i = 0; i < rule.length(); i++) + { char c = rule.charAt(i); + if (c == '|' && i + 2 < rule.length() && rule.charAt(i+1) == '-' && + rule.charAt(i+2) == '-' && rule.charAt(i+3) == '>') + { String lhs = rule.substring(0,i); + nospacelexicalanalysis(lhs); + + Vector variables = new Vector(); + for (int k = 0; k < lexicals.size(); k++) + { String lex = lexicals.get(k) + ""; + if (lex.startsWith("_")) + { variables.add(lex); } + } + + // System.out.println("LHS variables = " + variables); + + if (lhs != null) + { String rhs = rule.substring(i+4,rule.length()); + for (int j = 0; j < rhs.length(); j++) + { char d = rhs.charAt(j); + if (d == '<' && j+5 < rhs.length() && + rhs.charAt(j+1) == 'w' && + rhs.charAt(j+2) == 'h' && + rhs.charAt(j+3) == 'e' && + rhs.charAt(j+4) == 'n' && + rhs.charAt(j+5) == '>') + { String conditions = rhs.substring(j+6,rhs.length()); + Vector conds = parseCGconditions(conditions); + String rhstext = rhs.substring(0,j); + CGRule r = new CGRule(lhs,rhstext,variables,conds); + return r; + } + } + CGRule res = new CGRule(lhs,rhs,variables,new Vector()); + return res; + } + } + } + System.err.println(">>> Invalid rule: " + rule); + return null; + } + + public CGRule parse_OperationCodegenerationrule(String rule) + { String buff = ""; + for (int i = 0; i < rule.length(); i++) + { char c = rule.charAt(i); + if (c == '|' && i + 2 < rule.length() && rule.charAt(i+1) == '-' && + rule.charAt(i+2) == '-' && rule.charAt(i+3) == '>') + { String lhs = rule.substring(0,i); + nospacelexicalanalysis(lhs); + + Vector variables = new Vector(); + for (int k = 0; k < lexicals.size(); k++) + { String lex = lexicals.get(k) + ""; + if (lex.startsWith("_")) + { variables.add(lex); } + } + + System.out.println("LHS variables = " + variables); + + if (lhs != null) + { String rhs = rule.substring(i+4,rule.length()); + for (int j = 0; j < rhs.length(); j++) + { char d = rhs.charAt(j); + if (d == '<' && j+5 < rhs.length() && + rhs.charAt(j+1) == 'w' && + rhs.charAt(j+2) == 'h' && + rhs.charAt(j+3) == 'e' && + rhs.charAt(j+4) == 'n' && + rhs.charAt(j+5) == '>') + { String conditions = rhs.substring(j+6,rhs.length()); + Vector conds = parseCGconditions(conditions); + String rhstext = rhs.substring(0,j); + CGRule r = new CGRule(lhs,rhstext,variables,conds); + return r; + } + } + CGRule res = new CGRule(lhs,rhs,variables,new Vector()); + return res; + } + } + } + System.err.println(">>> Invalid rule: " + rule); + return null; + } + + public Vector parseCGconditions(String str) + { Vector conds = new Vector(); + StringTokenizer st = + new StringTokenizer(str); + + CGCondition cg = new CGCondition(); + + while (st.hasMoreTokens()) + { String se = st.nextToken().trim(); + if (",".equals(se)) + { conds.add(cg); + cg = new CGCondition(); + } + else if (se.startsWith("_")) + { cg.setVariable(se); } + else if (se.equals("not")) + { cg.setNegative(); } + else + { cg.setStereotype(se); } + } + conds.add(cg); + return conds; + } + + public Expression parseCGRule() + { System.out.println("LEXICALS: " + lexicals); + Expression ee = parseCGRule(0,0,lexicals.size()-1); + finalexpression = ee; + return ee; + } + + public Expression parseCGRule(int bcount, int pstart, int pend) + { // expr with _ |-> expr with _ conditions + for (int i = pstart; i <= pend; i++) + { String lx = lexicals.get(i) + ""; + if (lx.equals("|") && i + 1 <= pend && + "->".equals(lexicals.get(i+1) + "")) + { // System.out.println(">>> Deliminter at token " + i); + Expression lhs = parse_expression(bcount,pstart,i-1); + Expression rhs = null; + System.out.println("LHS = " + rhs); + + for (int j = i+2; j <= pend; j++) + { String lxj = lexicals.get(j) + ""; + if ("<".equals(lxj) && j+1 < pend && "when".equals(lexicals.get(j+1) + "") && + ">".equals(lexicals.get(j+2) + "")) + { rhs = parse_expression(bcount,i+2,j-1); + System.out.println("RHS = " + rhs); + } + } + if (rhs == null) // no + { rhs = parse_expression(bcount,i+2,pend); + System.out.println("RHS = " + rhs); + } + return lhs; + } + } + return null; + } + + public Expression parse() + { // System.out.println("LEXICALS: " + lexicals); + Expression ee = parse_expression(0,0,lexicals.size()-1); + finalexpression = ee; + return ee; + } + + public Expression parseExpression() + { // System.out.println("LEXICALS: " + lexicals); + Expression ee = parse_expression(0,0,lexicals.size()-1); + finalexpression = ee; + return ee; + } + + public Expression parse_expression(int bcount, int pstart, int pend) + { Expression ee = null; + + if ("if".equals(lexicals.get(pstart) + "") && "endif".equals(lexicals.get(pend) + "")) + { ee = parse_conditional_expression(bcount,pstart,pend); + if (ee != null) { return ee; } + } + + if ("not".equals(lexicals.get(pstart) + "")) + { ee = parse_expression(bcount,pstart+1,pend); + if (ee != null) + { return new UnaryExpression("not", ee); } + } + + if ("_".equals(lexicals.get(pstart) + "") && pend == pstart+1) + { ee = parse_expression(bcount,pstart+1,pend); + if (ee != null) + { return new UnaryExpression("_", ee); } + } + + OpOccurrence op = getBestOcc(pstart,pend); + if (op == null) // No logical ops here + { ee = parse_eq_expression(bcount,pstart,pend); + if (ee == null) + { ee = parse_factor_expression(bcount,pstart,pend); } + return ee; + } + if (op.bcount > bcount) // bracketed expression + { ee = parse_eq_expression(bcount,pstart,pend); + if (ee == null) + { ee = parse_factor_expression(bcount,pstart,pend); } + return ee; + } + else + { ee = parse_implies_expression(bcount,pstart,pend,op.location,op.op); } + return ee; + } + + + /* public Expression parse_binary_expression(int pstart, + int pend) + { + Expression ee = parse_implies_expression(pstart,pend); + if (ee == null) + { ee = parse_or_expression(pstart,pend); + if (ee == null) + { ee = parse_and_expression(pstart,pend); + if (ee == null) + { ee = parse_eq_expression(pstart,pend); + if (ee == null) + { ee = parse_factor_expression(pstart,pend); } + } + } + } + return ee; + } */ + +public Expression parse_conditional_expression(int bc, int st, int en) +{ // st is "if", en is "endif" + int ifcount = 1; + String lxst = lexicals.get(st) + ""; + String lxen = lexicals.get(en) + ""; + if ("if".equals(lxst) && "endif".equals(lxen)) {} + else { return null; } + for (int j = st+1; j < en; j++) + { String lxj = lexicals.get(j) + ""; + if ("if".equals(lxj)) + { ifcount++; } + else if ("endif".equals(lxj)) + { ifcount--; + if (ifcount < 1) + { System.err.println("Too many endifs"); return null; } + } + else if ("then".equals(lxj) && ifcount == 1) + { Expression test = parse_expression(bc, st+1, j-1); + if (test == null) + { System.err.println("Error in if test expression"); return null; } + int ifcountk = 1; + for (int k = j+1; k < en; k++) + { String lxk = lexicals.get(k) + ""; + if ("if".equals(lxk)) + { ifcountk++; } + else if ("endif".equals(lxk)) + { ifcountk--; + if (ifcountk < 1) + { System.err.println("Too many endifs"); return null; } + } + else if ("else".equals(lxk) && ifcountk == 1) + { Expression ifpart = parse_expression(bc, j+1, k-1); + Expression elsepart = parse_expression(bc, k+1, en-1); + if (ifpart != null && elsepart != null) + { return new ConditionalExpression(test,ifpart,elsepart); } else { return null; } + } else { } + } // k loop + } else { } + } // j loop + return null; +} + +public Expression parse_ATLconditional_expression(int bc, int st, int en, Vector entities, Vector types) +{ // st is "if", en is "endif" + int ifcount = 1; + String lxst = lexicals.get(st) + ""; + String lxen = lexicals.get(en) + ""; + if ("if".equals(lxst) && "endif".equals(lxen)) {} + else { return null; } + for (int j = st+1; j < en; j++) + { String lxj = lexicals.get(j) + ""; + if ("if".equals(lxj)) + { ifcount++; } + else if ("endif".equals(lxj)) + { ifcount--; + if (ifcount < 1) + { System.err.println("Too many endifs"); return null; } + } + else if ("then".equals(lxj) && ifcount == 1) + { Expression test = parse_ATLexpression(bc, st+1, j-1,entities,types); + if (test == null) + { System.err.println("Error in if test expression"); return null; } + int ifcountk = 1; + for (int k = j+1; k < en; k++) + { String lxk = lexicals.get(k) + ""; + if ("if".equals(lxk)) + { ifcountk++; } + else if ("endif".equals(lxk)) + { ifcountk--; + if (ifcountk < 1) + { System.err.println("Too many endifs"); return null; } + } + else if ("else".equals(lxk) && ifcountk == 1) + { Expression ifpart = parse_ATLexpression(bc, j+1, k-1,entities,types); + Expression elsepart = parse_ATLexpression(bc, k+1, en-1, entities,types); + if (ifpart != null && elsepart != null) + { return new ConditionalExpression(test,ifpart,elsepart); } else { return null; } + } else { } + } // k loop + } else { } + } // j loop + return null; +} + +/* Only for ATL, ETL, QVT-R */ +public Expression parse_let_expression(int bc, int st, int en, Vector entities, Vector types) +{ // let v : T = e in expr + // a BinaryExpression with operator "let" and accumulator v : T + + int letcount = 1; + String lxst = lexicals.get(st) + ""; + if ("let".equals(lxst)) {} + else { return null; } + + for (int j = st+1; j < en; j++) + { String lxj = lexicals.get(j) + ""; + if ("let".equals(lxj)) + { letcount++; } + else if ("in".equals(lxj)) + { if (letcount > 1) // an inner let + { letcount--; } + else if (letcount < 1) + { System.err.println("Too many in clauses"); return null; } + else + { Expression var = parse_ATLexpression(bc, st+1, st+1,entities,types); + if (var == null) + { System.err.println("Error in let variable"); return null; } + + for (int k = st+2; k < j; k++) + { String lxk = lexicals.get(k) + ""; + if ("=".equals(lxk)) + { Type ltype = parseType(st+3,k-1,entities,types); + if (ltype == null) + { System.err.println("Error in let type"); return null; } + + Expression lexp = parse_ATLexpression(bc,k+1,j-1,entities,types); + if (lexp == null) + { System.err.println("Error in let definition expression"); return null; } + + Expression lbody = parse_ATLexpression(bc,j+1,en,entities,types); + if (lbody == null) + { System.err.println("Error in let body"); } + + if (ltype != null && lexp != null && lbody != null) + { BinaryExpression letexp = new BinaryExpression("let", lexp, lbody); + letexp.accumulator = new Attribute(var + "", ltype, ModelElement.INTERNAL); + return letexp; + // return new LetExpression(var,ltype,lexp,lbody); + } + } + } // k loop + } + } else { } + } // j loop + return null; +} + + public BinaryExpression parse_implies_expression(int bcount, int pstart, + int pend, int pos, String op) + { // There must be a logical operator at top level in the expression + Expression e1 = null; + Expression e2 = null; + // System.out.println("Trying to parse logical expression"); + // System.out.println("Trying at: " + pos + " " + op); + e1 = parse_expression(bcount,pstart,pos-1); + + // if (e1 == null) + // { System.err.println("Invalid expression: " + showLexicals(pstart, pos-1)); } + + e2 = parse_expression(bcount,pos+1,pend); + + // if (e2 == null) + // { System.err.println("Invalid expression: " + showLexicals(pos + 1, pend)); } + + if (e1 == null || e2 == null) + { System.out.println("Failed to parse: " + showLexicals(pstart, pend)); + return null; + } + else + { BinaryExpression ee = new BinaryExpression(op,e1,e2); + // System.out.println("Parsed implies expression: " + ee); + return ee; + } + } + + public String showLexicals(int st, int en) + { String res = ""; + for (int i = st; i <= en; i++) + { res = res + lexicals.get(i) + " "; } + return res; + } + + /* public BinaryExpression parse_or_expression(int pstart, + int pend) + { + Expression e1 = null; + Expression e2 = null; + + System.out.println("Trying to parse or expression"); + + for (int i = pstart; i < pend; i++) + { + String ss = lexicals.elementAt(i).toString(); + if (ss.equals("or")) + { + e1 = parse_binary_expression(pstart,i-1); + e2 = parse_binary_expression(i+1,pend); + if (e1 == null || e2 == null) + { } // return null; } + else + { BinaryExpression ee = new BinaryExpression(ss,e1,e2); + System.out.println("Parsed or expression: " + ee); + return ee; } + } + } + return null; + } + + public BinaryExpression parse_and_expression(int pstart, + int pend) + { + Expression e1 = null; + Expression e2 = null; + + System.out.println("Trying to parse and expression"); + int best = getBestAndOpOccurrence(pstart,pend); + + // for (int i = pstart; i < pend; i++) + // + if (best <= pend) + { + String ss = (String) lexs.get(best); + if (ss.equals("&")) + { System.out.println("trying & op at position " + best); + e1 = parse_binary_expression(pstart,best-1); + e2 = parse_binary_expression(best+1,pend); + if (e1 == null || e2 == null) + { return null; } + else + { BinaryExpression ee = new BinaryExpression(ss,e1,e2); + System.out.println("Parsed and expression: " + ee); + return ee; + } + } + } + return null; + } */ + + + public Expression parse_eq_expression(int bc, int pstart, + int pend) + { Expression e1 = null; + Expression e2 = null; + + // System.out.println("Trying to parse eq. expression"); + + for (int i = pstart; i < pend; i++) + { + String ss = lexicals.elementAt(i).toString(); + if (ss.equals(":=") || ss.equals(":") || ss.equals("<:") || + ss.equals("/:") || ss.equals("/<:") || ss.equals("<>") || + Expression.comparitors.contains(ss)) + { e1 = parse_additive_expression(bc,pstart,i-1); + e2 = parse_additive_expression(bc,i+1,pend); + if (e1 == null || e2 == null) + { } // return null; } + else + { BinaryExpression ee = new BinaryExpression(ss,e1,e2); + // System.out.println("Parsed equality expression: " + ee); + return ee; + } + } + } + return parse_additive_expression(bc,pstart,pend); + // return null; + } // <> is only for ATL + + public Expression parse_additive_expression(int bc, int pstart, int pend) + { for (int i = pstart; i < pend; i++) + { String ss = lexicals.get(i).toString(); + if (ss.equals("+") || ss.equals("-") || ss.equals("\\/")) + { Expression e1 = parse_factor_expression(bc,pstart,i-1); + Expression e2 = parse_additive_expression(bc,i+1,pend); + if (e1 == null || e2 == null) + { } // return null; } + else + { BinaryExpression ee = new BinaryExpression(ss,e1,e2); + // System.out.println("Parsed additive expression: " + ee); + return ee; + } + } + } + return parse_factor_expression(bc,pstart,pend); + } // reads left to right, not putting priorities on * above + + + public Expression parse_factor_expression(int bc, int pstart, int pend) + { // System.out.println("Trying to parse factor expression"); + for (int i = pstart; i < pend; i++) + { String ss = lexicals.get(i).toString(); + if // (ss.equals("+") || ss.equals("-") || + (ss.equals("/\\") || ss.equals("^") || + ss.equals("*") || ss.equals("/") || ss.equals("div") || + ss.equals("mod")) + { Expression e1 = parse_basic_expression(bc,pstart,i-1); // factor2 + Expression e2 = parse_factor_expression(bc,i+1,pend); + if (e1 == null || e2 == null) + { } // return null; } + else + { BinaryExpression ee = new BinaryExpression(ss,e1,e2); + // System.out.println("Parsed factor expression: " + ee); + return ee; + } + } + } + return parse_factor2_expression(bc,pstart,pend); + } // reads left to right, not putting priorities on * above + + // div is only for ATL. + + public Expression parse_factor2_expression(int bc, int pstart, int pend) + { // System.out.println("Trying to parse factor2 expression from " + pstart + " to " + pend); + // case of argument->op() and left->op(right) + + for (int i = pend-1; pstart < i; i--) + { String ss = lexicals.get(i).toString(); + if (ss.equals("->") && "(".equals(lexicals.get(i+2) + "") && + ")".equals(lexicals.get(pend) + "")) + { String ss2 = lexicals.get(i+1).toString(); // must exist + if (i + 3 == pend && + ("any".equals(ss2) || "size".equals(ss2) || "isDeleted".equals(ss2) || + "display".equals(ss2) || "min".equals(ss2) || "max".equals(ss2) || + "sum".equals(ss2) || "sort".equals(ss2) || "asSet".equals(ss2) || + "sqrt".equals(ss2) || "sqr".equals(ss2) || "asSequence".equals(ss2) || + "last".equals(ss2) || "first".equals(ss2) || "closure".equals(ss2) || + "subcollections".equals(ss2) || "reverse".equals(ss2) || "prd".equals(ss2) || + "tail".equals(ss2) || "front".equals(ss2) || "isEmpty".equals(ss2) || + "notEmpty".equals(ss2) || "toUpperCase".equals(ss2) || "flatten".equals(ss2) || + "toLowerCase".equals(ss2) || "isInteger".equals(ss2) || "toLong".equals(ss2) || + "toInteger".equals(ss2) || "isReal".equals(ss2) || "toReal".equals(ss2) || + "exp".equals(ss2) || "log".equals(ss2) || "log10".equals(ss2) || + "sin".equals(ss2) || "cos".equals(ss2) || "allInstances".equals(ss2) || + "tan".equals(ss2) || "oclIsUndefined".equals(ss2) || + "floor".equals(ss2) || "ceil".equals(ss2) || "round".equals(ss2) || + "abs".equals(ss2) || "cbrt".equals(ss2) || "asin".equals(ss2) || + "acos".equals(ss2) || "atan".equals(ss2) || "isLong".equals(ss2) || + "sinh".equals(ss2) || "cosh".equals(ss2) || "tanh".equals(ss2) || + "values".equals(ss2) || "keys".equals(ss2) ) ) + { Expression ee2 = parse_factor_expression(bc,pstart,i-1); + if (ee2 == null) + { // System.err.println("Invalid unary -> expression at: " + showLexicals(pstart,pend)); + continue; + } + UnaryExpression ue = new UnaryExpression(ss+ss2,ee2); + // System.out.println("Parsed unary expression: " + ue); + return ue; // This excludes additional operators to the ones listed above. + } + else if ("exists".equals(ss2) && + i+5 < pend && // "(".equals(lexicals.get(i+2) + "") && + "|".equals(lexicals.get(i+4) + "") && + ")".equals(lexicals.get(pend) + "")) + { // It is ->exists(v|...) + Expression ee1 = parse_expression(bc+1,i+5,pend-1); + if (ee1 == null) { continue; } + Expression ee2 = parse_factor_expression(bc,pstart,i-1); + if (ee2 == null) { continue; } + BasicExpression bevar = + new BasicExpression(lexicals.get(i+3) + "",0); + BinaryExpression be = + new BinaryExpression("#",new BinaryExpression(":",bevar,ee2),ee1); + // System.out.println("Parsed: " + be); + return be; + } + else if (("exists1".equals(ss2) || "one".equals(ss2)) && + i+5 < pend && "|".equals(lexicals.get(i+4) + "") && + // "(".equals(lexicals.get(i+2) + "") && + ")".equals(lexicals.get(pend) + "")) + { // It is ->exists1(v|...) + Expression ee1 = parse_expression(bc+1,i+5,pend-1); + if (ee1 == null) { continue; } + Expression ee2 = parse_factor_expression(bc,pstart,i-1); + if (ee2 == null) { continue; } + BasicExpression bevar = + new BasicExpression(lexicals.get(i+3) + "",0); + BinaryExpression be = + new BinaryExpression("#1",new BinaryExpression(":",bevar,ee2),ee1); + // System.out.println("Parsed: " + be); + return be; + } + else if ("existsLC".equals(ss2) && + i+5 < pend && "|".equals(lexicals.get(i+4) + "") && + // "(".equals(lexicals.get(i+2) + "") && + ")".equals(lexicals.get(pend) + "")) + { // It is ->existsLC(v|...) + Expression ee1 = parse_expression(bc+1,i+5,pend-1); + if (ee1 == null) { continue; } + Expression ee2 = parse_factor_expression(bc,pstart,i-1); + if (ee2 == null) { continue; } + BasicExpression bevar = + new BasicExpression(lexicals.get(i+3) + "",0); + BinaryExpression be = + new BinaryExpression("#LC",new BinaryExpression(":",bevar,ee2),ee1); + // System.out.println("Parsed: " + be); + return be; + } + else if ("forAll".equals(ss2) && + i+5 < pend && "|".equals(lexicals.get(i+4) + "") && + // "(".equals(lexicals.get(i+2) + "") && + ")".equals(lexicals.get(pend) + "")) + { // It is ->forAll(v|...) + Expression ee1 = parse_expression(bc+1,i+5,pend-1); + if (ee1 == null) { continue; } + Expression ee2 = parse_factor_expression(bc,pstart,i-1); + if (ee2 == null) { continue; } + BasicExpression bevar = + new BasicExpression(lexicals.get(i+3) + "",0); + BinaryExpression be = + new BinaryExpression("!",new BinaryExpression(":",bevar,ee2),ee1); + // System.out.println("Parsed: " + be); + return be; + } + else if ("select".equals(ss2) && + i+5 < pend && "|".equals(lexicals.get(i+4) + "") && + // "(".equals(lexicals.get(i+2) + "") && + ")".equals(lexicals.get(pend) + "")) + { // It is ->select(v|...) + Expression ee1 = parse_expression(bc+1,i+5,pend-1); + if (ee1 == null) { continue; } + Expression ee2 = parse_factor_expression(bc,pstart,i-1); + if (ee2 == null) { continue; } + BasicExpression bevar = + new BasicExpression(lexicals.get(i+3) + "",0); + BinaryExpression be = + new BinaryExpression("|",new BinaryExpression(":",bevar,ee2),ee1); + // System.out.println("Parsed: " + be); + return be; + } + else if ("reject".equals(ss2) && + i+5 < pend && "|".equals(lexicals.get(i+4) + "") && + // "(".equals(lexicals.get(i+2) + "") && + ")".equals(lexicals.get(pend) + "")) + { // It is ->reject(v|...) + Expression ee1 = parse_expression(bc+1,i+5,pend-1); + if (ee1 == null) { continue; } + Expression ee2 = parse_factor_expression(bc,pstart,i-1); + if (ee2 == null) { continue; } + BasicExpression bevar = + new BasicExpression(lexicals.get(i+3) + "",0); + BinaryExpression be = + new BinaryExpression("|R",new BinaryExpression(":",bevar,ee2),ee1); + // System.out.println("Parsed: " + be); + return be; + } + else if ("collect".equals(ss2) && + i+5 < pend && "|".equals(lexicals.get(i+4) + "") && + // "(".equals(lexicals.get(i+2) + "") && + ")".equals(lexicals.get(pend) + "")) + { // It is ->collect(v|...) + Expression ee1 = parse_expression(bc+1,i+5,pend-1); + if (ee1 == null) { continue; } + Expression ee2 = parse_factor_expression(bc,pstart,i-1); + if (ee2 == null) { continue; } + BasicExpression bevar = + new BasicExpression(lexicals.get(i+3) + "",0); + BinaryExpression be = + new BinaryExpression("|C",new BinaryExpression(":",bevar,ee2),ee1); + // System.out.println("Parsed: " + be); + return be; + } + else if ("any".equals(ss2) && + i+5 < pend && "|".equals(lexicals.get(i+4) + "") && + // "(".equals(lexicals.get(i+2) + "") && + ")".equals(lexicals.get(pend) + "")) + { // It is ->any(v|...) + Expression ee1 = parse_expression(bc+1,i+5,pend-1); + if (ee1 == null) { continue; } + Expression ee2 = parse_factor_expression(bc,pstart,i-1); + if (ee2 == null) { continue; } + BasicExpression bevar = + new BasicExpression(lexicals.get(i+3) + "",0); + BinaryExpression be = + new BinaryExpression("|A",new BinaryExpression(":",bevar,ee2),ee1); + // System.out.println("Parsed: " + be); + return be; + } + else if (pend == i+3) // && "(".equals(lexicals.get(i+2) + "") && + // ")".equals(lexicals.get(pend) + "")) + { Expression ee2 = parse_factor_expression(bc,pstart,i-1); + if (ee2 == null) { continue; } + UnaryExpression be = new UnaryExpression(ss+ss2,ee2); + // System.out.println("Parsed new unary -> expression: " + be); + return be; + } + else if (i + 3 <= pend) // && "(".equals(lexicals.get(i+2) + "") && + // ")".equals(lexicals.get(pend) + "")) + // this should allow new Binary operators + { // System.out.println("Tring tp parse at " + ss2); + Expression ee1 = parse_expression(bc+1,i+3,pend-1); + if (ee1 == null) { continue; } + Expression ee2 = parse_factor_expression(bc,pstart,i-1); + if (ee2 == null) { continue; } + BinaryExpression be = new BinaryExpression(ss+ss2,ee2,ee1); + System.out.println("Parsed binary -> expression: " + be); + return be; + } + } + } + return parse_basic_expression(bc,pstart,pend); + } // reads left to right, not putting priorities on * above + + + // add the case for ->iterate + + public Expression parse_basic_expression(int bc, int pstart, int pend) + { // System.out.println("Trying tp parse basic expression from " + pstart + " to " + pend); + + // if ("_".equals(lexicals.get(pstart) + "") && pend == pstart+1) + // { Expression ee = parse_expression(bc,pstart+1,pend); + // if (ee != null) + // { return new UnaryExpression("_", ee); } + // } + + if (pstart == pend) + { String ss = lexicals.elementAt(pstart).toString(); + if (invalidBasicExp(ss)) + { // System.err.println("!!! ERROR: Invalid basic expression: " + ss); + return null; + } + if (isKeyword(ss)) + { System.err.println(">>>: Invalid basic expression: keyword: " + ss); + return null; + } + + BasicExpression ee = // new BasicExpression(ss,0); // (ss) surely? + new BasicExpression(ss,0); + Expression ef = ee.checkIfSetExpression(); + + // if (ef instanceof BasicExpression) + // { ((BasicExpression) ef).setPrestate(ee.getPrestate()); } + + // System.out.println("Parsed basic expression: " + ss + " " + ee + " " + ef); + return ef; + } + + if (pstart < pend && "}".equals(lexicals.get(pend) + "") && + "{".equals(lexicals.get(pstart) + "")) + { return parse_set_expression(bc,pstart,pend); } + + if (pstart < pend && "}".equals(lexicals.get(pend) + "") && + "Sequence".equals(lexicals.get(pstart) + "") && + "{".equals(lexicals.get(pstart + 1) + "")) + { return parse_sequence_expression(bc,pstart+1,pend); } + + if (pstart < pend && "}".equals(lexicals.get(pend) + "") && + "Set".equals(lexicals.get(pstart) + "") && + "{".equals(lexicals.get(pstart + 1) + "")) + { return parse_set_expression(bc,pstart+1,pend); } + + if (pstart < pend && "-".equals(lexicals.get(pstart) + "")) + { Expression arg = parse_additive_expression(bc,pstart+1,pend); + if (arg == null) + { System.err.println("Not additive expression: " + showLexicals(pstart+1, pend)); + return null; + } + return new UnaryExpression("-",arg); + } // likewise for "not" + + if (pstart + 1 < pend && ")".equals(lexicals.get(pend) + "") && + "(".equals(lexicals.get(pstart+1) + "")) + { Expression op = parse_basic_expression(bc,pstart,pstart); + + Vector ve = parse_fe_sequence(bc,pstart+2,pend-1); + if (ve != null && op != null && op instanceof BasicExpression) // must be + { BasicExpression beop = (BasicExpression) op; + + if (Expression.isFunction(beop.data)) + { beop.umlkind = Expression.FUNCTION; } + else + { beop.setIsEvent(); } + + beop.setParameters(ve); + // System.out.println("Parsed call expression: " + beop); + return beop; + } + // return null; + } + + if (pstart + 2 < pend && ")".equals(lexicals.get(pend) + "") && + "(".equals(lexicals.get(pstart+2) + "") && + ("" + lexicals.get(pstart + 1)).charAt(0) == '.') + { // iden.op(args) + Expression objref = parse_basic_expression(bc,pstart,pstart); + String opstring = lexicals.get(pstart + 1) + ""; + String opstr = opstring.substring(1,opstring.length()); + + Vector ve = parse_fe_sequence(bc,pstart+3,pend-1); + if (ve != null && objref != null && objref instanceof BasicExpression) // must be + { BasicExpression beopref = (BasicExpression) objref; + BasicExpression beop = new BasicExpression(opstr); + + if (Expression.isFunction(opstr)) + { beop.umlkind = Expression.FUNCTION; } + else + { beop.setIsEvent(); } + + beop.setParameters(ve); + beop.setObjectRef(beopref); + // System.out.println("Parsed call expression: " + beop); + return beop; + } + // return null; + } + + if (pstart < pend && "]".equals(lexicals.get(pend) + "") && + "[".equals(lexicals.get(pstart+1) + "")) + { String ss = lexicals.elementAt(pstart).toString(); + BasicExpression ee = new BasicExpression(ss,0); + Expression op = ee.checkIfSetExpression(); + // Expression op = parse_basic_expression(bc,pstart,pstart); + Expression arg = parse_additive_expression(bc,pstart+2,pend-1); + if (arg == null) + { System.err.println("ERROR: Invalid array argument: " + showLexicals(pstart+2,pend-1)); } + else if (op != null && op instanceof BasicExpression) // must be + { BasicExpression beop = (BasicExpression) op; + beop.setArrayIndex(arg); + // System.out.println("Parsed array expression: " + beop); + return beop; + } + // return null; + } + + if (pstart < pend && "]".equals(lexicals.get(pend-1) + "") && + "[".equals(lexicals.get(pstart+1) + "")) // be[arrind].be2 + { String tail = lexicals.get(pend) + ""; + if (tail.charAt(0) == '.') + { tail = tail.substring(1,tail.length()); } + Expression op = parse_basic_expression(bc,pstart,pstart); + Expression arg = parse_additive_expression(bc,pstart+2,pend-2); + if (arg == null) + { System.err.println("ERROR: Invalid array argument: " + showLexicals(pstart+2,pend-2)); } + else if (op != null && op instanceof BasicExpression) // must be + { BasicExpression beop = (BasicExpression) op; + beop.setArrayIndex(arg); + BasicExpression te = // new BasicExpression(ss,0); // (ss) surely? + new BasicExpression(tail,0); + Expression ef = te.checkIfSetExpression(); + if (ef != null && (ef instanceof BasicExpression)) + { ((BasicExpression) ef).setInnerObjectRef(beop); } + // System.out.println("Parsed array 1 expression: " + ef); + return ef; + } + // return null; + } + + if (pstart + 1 < pend && ")".equals(lexicals.get(pend) + "") && + !("(".equals(lexicals.get(pstart) + ""))) + { for (int i = pstart + 1; i < pend; i++) + { String strs = lexicals.get(i) + ""; + if ("(".equals(strs)) + { Expression op = parse_basic_expression(bc, pstart, i-1); + if (op != null && op instanceof BasicExpression) + { Vector ve = parse_fe_sequence(bc,i+1,pend-1); + if (ve != null) + { BasicExpression beop = (BasicExpression) op; + beop.setIsEvent(); + beop.setParameters(ve); + // System.out.println("Parsed extended call expression " + beop); + return beop; + } + } + } + } + } + + /* if (pstart < pend && + "[".equals(lexicals.get(pstart+1) + "")) // be[arrind].something + { for (int k = pstart + 2; k < pend; k++) + { String kstring = lexicals.get(k) + ""; + if ("]".equals(kstring)) + { Expression op = parse_basic_expression(bc,pstart,pstart); + Expression arg = parse_factor_expression(bc,pstart+2,k-1); + + String tail = lexicals.get(k+1) + ""; + if (tail.charAt(0) == '.') + { tail = tail.substring(1,tail.length()); } + if (op instanceof BasicExpression) // must be + { BasicExpression beop = (BasicExpression) op; + beop.setArrayIndex(arg); + Expression te = parse_basic_expression(bc,k+1,pend); + if (te != null) + { if (te instanceof BasicExpression) + { BasicExpression bte = (BasicExpression) te; + bte.setData(tail); + bte.setObjectRef(beop); + System.out.println("Parsed array 2 expression: " + bte); + return bte; + } + else + { return null; } + } + } + } + } + return null; + } */ + + return parse_bracketed_expression(bc,pstart,pend); + } + + public Expression parse_set_expression(int bc,int pstart,int pend) + { Vector ve = parse_fe_sequence(bc,pstart+1,pend-1); + if (ve == null) + { return null; } + Expression res = new SetExpression(ve,false); + // System.out.println("Parsed set expression: " + res); + return res; + } + + public Expression parse_sequence_expression(int bc,int pstart,int pend) + { Vector ve = parse_fe_sequence(bc,pstart+1,pend-1); + if (ve == null) + { return null; } + Expression res = new SetExpression(ve,true); + // System.out.println("Parsed sequence expression: " + res); + return res; + } + + public Expression parse_map_expression(int bc,int pstart,int pend, Vector entities, Vector types) + { Vector ve = parse_map_sequence(bc,pstart+1,pend-1,entities,types); + if (ve == null) + { return null; } + Expression res = new SetExpression(ve,true); + res.setType(new Type("Map",null)); + // System.out.println("Parsed map expression: " + res); + return res; + } + + public Vector parse_fe_sequence(int bc, int st, int ed) + { Vector res = new Vector(); + // if (st == ed) // just one basic exp + // { Expression elast = parse_basic_expression(bc,st,ed); + // res.add(elast); + // return res; + // } + if (st > ed) + { return res; } + return getFESeq(bc,st,ed); + + // Only commas at the top level of the expression are wanted! + /* + for (int i = st; i < ed; i++) + { String ss = lexicals.get(i) + ""; + if (",".equals(ss)) + { Expression e1 = parse_factor_expression(bc,st,i-1); + if (e1 == null) + { continue; } // skip this comma + res = parse_fe_sequence(bc,i+1,ed); + if (res == null) + { continue; } // skip this comma + res.add(0,e1); + return res; + } + } + Expression elast = parse_factor_expression(bc,st,ed); + if (elast != null) + { res.add(elast); } + return res; + */ + } + + private Vector getFESeq(int bc, int st, int en) + { // Scans the lexicals inside the outer brackets of + // a potential fe-sequence + + int bcnt = 0; int sqbcnt = 0; int cbcnt = 0; + Vector res = new Vector(); + int st0 = st; + String buff = ""; + for (int i = st; i <= en; i++) + { String lx = lexicals.get(i) + ""; + buff = buff + lx; + if ("(".equals(lx)) { bcnt++; } + else if (")".equals(lx)) + { bcnt--; + if (bcnt < 0) { return null; } + } + else if ("[".equals(lx)) { sqbcnt++; } + else if ("]".equals(lx)) { sqbcnt--; } + else if ("{".equals(lx)) { cbcnt++; } + else if ("}".equals(lx)) { cbcnt--; } + else if (",".equals(lx)) + { if (bcnt == 0 && sqbcnt == 0 && cbcnt == 0) + { // top-level , + Expression exp = parse_additive_expression(bc,st0,i-1); + if (exp == null) + { System.out.println("Invalid additive exp: " + buff); + return null; + } + res.add(exp); + st0 = i + 1; + buff = ""; + } + } + } + // at the end: + if (bcnt == 0 && sqbcnt == 0 && cbcnt == 0) + { Expression exp = parse_additive_expression(bc,st0,en); + if (exp == null) + { System.out.println("Invalid additive exp: " + buff); + return null; + } + res.add(exp); + } + else + { // System.err.println("Not fe sequence: " + showLexicals(st,en)); + return null; + } + return res; + } + + public Vector parse_map_sequence(int bc, int st, int ed, Vector entities, Vector types) + { Vector res = new Vector(); + if (st > ed) + { return res; } + return getMapSeq(bc,st,ed,entities,types); + } + + private Vector getMapSeq(int bc, int st, int en, Vector entities, Vector types) + { // Scans the lexicals inside the outer brackets of + // a potential fe-sequence + + int bcnt = 0; int sqbcnt = 0; int cbcnt = 0; + Vector res = new Vector(); + int st0 = st; + String buff = ""; + for (int i = st; i <= en; i++) + { String lx = lexicals.get(i) + ""; + buff = buff + lx; + if ("(".equals(lx)) { bcnt++; } + else if (")".equals(lx)) + { bcnt--; + if (bcnt < 0) { return null; } + } + else if ("[".equals(lx)) { sqbcnt++; } + else if ("]".equals(lx)) { sqbcnt--; } + else if ("{".equals(lx)) { cbcnt++; } + else if ("}".equals(lx)) { cbcnt--; } + else if (",".equals(lx)) + { if (bcnt == 0 && sqbcnt == 0 && cbcnt == 0) + { // top-level , + Expression exp = parse_pair_expression(bc,st0,i-1,entities,types); + if (exp == null) + { System.out.println("Invalid pair exp: " + buff); + return null; + } + exp.setBrackets(true); + res.add(exp); + st0 = i + 1; + buff = ""; + } + } + } + // at the end: + if (bcnt == 0 && sqbcnt == 0 && cbcnt == 0) + { Expression exp = parse_pair_expression(bc,st0,en,entities,types); + if (exp == null) + { System.out.println("Invalid pair exp: " + buff); + return null; + } + exp.setBrackets(true); + res.add(exp); + } + else + { System.err.println("Not fe sequence: " + showLexicals(st,en)); + return null; + } + return res; + } + + public Expression parse_pair_expression(int bc, int st, int en, Vector entities, Vector types) + { // st is "(" and en is ")" + for (int i = st+1; i < en; i++) + { String ss = lexicals.get(i) + ""; + if (",".equals(ss)) + { Expression e1 = parse_ATLexpression(bc,st + 1, i-1,entities,types); + Expression e2 = parse_ATLexpression(bc,i+1, en-1,entities,types); + if (e1 != null && e2 != null) + { return new BinaryExpression(",", e1, e2); } + } + } + return null; + } + + + + + public BehaviouralFeature operationDefinition(Vector entities, Vector types) + { return operationDefinition(0, lexicals.size()-1, entities, types); } + + +public BehaviouralFeature operationDefinition(int st, int en, Vector entities, Vector types) +{ if (en <= st) { return null; } + boolean valid = false; + boolean foundpre = false; + boolean foundpost = false; + + String opname = lexicals.get(st) + ""; + BehaviouralFeature bf = new BehaviouralFeature(opname); + int st0 = st + 1; + for (int i = st0; i < en; i++) + { String lx = lexicals.get(i) + ""; + String lx1 = lexicals.get(i+1) + ""; + if (lx.equals("pre") && lx1.equals(":")) + { parseOpDecs(st+1,i-1,entities,types,bf); + foundpre = true; + st0 = i+2; + } + else if (lx.equals("post") && lx1.equals(":")) + { Expression pre = parse_expression(0,st0,i-1); + if (pre == null) + { System.err.println("ERROR: Invalid precondition: " + showLexicals(st0,i-1)); + pre = new BasicExpression(true); + } + foundpre = true; + foundpost = true; + + bf.setPre(pre); + valid = true; + st0 = i+2; + for (int j = st0; j < en; j++) + { String jx = lexicals.get(j) + ""; + if ("activity".equals(jx) && ":".equals(lexicals.get(j+1) + "")) + { st0 = j+2; + Expression pots = parse_expression(0,i+2,j-1); + if (pots == null) + { System.err.println("ERROR: Invalid postcondition: " + showLexicals(i+2,en)); + bf.setPost(new BasicExpression(true)); + } + else + { bf.setPost(pots); } + Statement act = parseStatement(j+2,en,entities,types); + if (act == null) + { System.err.println("ERROR: Invalid postcondition: " + showLexicals(i+2,en)); } + bf.setActivity(act); + return bf; + } + } + } + } + + /* Expression pst = parse_expression(0,st0,en); + if (pst == null) + { System.err.println("ERROR: Invalid postcondition: " + showLexicals(st0,en)); + bf.setPost(new BasicExpression(true)); + } + else + { bf.setPost(pst); + valid = true; + } */ + + if (foundpost == false) + { System.err.println("**** Invalid operation definition, no postcondition: " + showLexicals(st,en)); + parseOpDecs(st+1,en,entities,types,bf); + } + else + { Expression pst = parse_expression(0,st0,en); + if (pst == null) + { System.err.println("ERROR: Invalid postcondition: " + showLexicals(st0,en)); + bf.setPost(new BasicExpression(true)); + } + else + { bf.setPost(pst); + valid = true; + } + } + + return bf; +} + + + +private void parseOpDecs(int st, int en, Vector entities, Vector types, BehaviouralFeature bf) +{ int bcnt = 0; int st0 = st+1; + int np = 0; + + int bracketend = en; + for (int i = st; i <= en; i++) + { String lex = lexicals.get(i) + ""; + if ("(".equals(lex)) { bcnt++; } + else if (")".equals(lex)) + { bcnt--; + if (bcnt == 0) + { bracketend = i; + break; + } + } + else if (":".equals(lex)) + { np++; } + } + bcnt = 0; + + // System.out.println(np + " Parameters"); + + + Vector res = new Vector(); + for (int j = st; j <= en; j++) + { String lx = lexicals.get(j) + ""; + if ("(".equals(lx)) { bcnt++; } + else if (")".equals(lx)) + { bcnt--; + if (bcnt < 0) + { System.err.println("*** Extra closing bracket in declaration: " + showLexicals(st,j)); + return; + } + } + else if (":".equals(lx) && bcnt == 1) + { String attnme = lexicals.get(j-1) + ""; + Attribute att = null; + for (int k = j+1; k <= bracketend; k++) + { String lxk = lexicals.get(k) + ""; + if (":".equals(lxk)) + { att = parseParameterDec(j-1, k-3, entities, types); + if (att == null) + { System.err.println("*** Invalid parameter syntax: " + showLexicals(st0,j-1)); } + else + { System.out.println("*** Parsed parameter: " + att + " type: " + att.getType() + " " + + att.getElementType()); + bf.addParameter(att); + } + st0 = k+1; + break; + } + } + if (att == null) + { att = parseParameterDec(j-1, bracketend-1, entities, types); + if (att != null) + { System.out.println("*** Parsed parameter: " + att + " type: " + att.getType() + " " + + att.getElementType()); + bf.addParameter(att); + st0 = bracketend + 1; + } + } + } + else if (":".equals(lx) && bcnt == 0) + { Type rt = parseType(j+1,en,entities,types); + if (rt == null) + { System.err.println("*** ERROR: Invalid return type: " + showLexicals(j+1, en)); + bf.setQuery(false); + } + else if ("void".equals(rt + "")) + { bf.setQuery(false); } + else + { bf.setQuery(true); } + bf.setResultType(rt); + } // it is query unless the result type is null or void. + } + + if (bcnt > 0) + { System.err.println("*** Unclosed bracket in declaration: " + showLexicals(st,en)); } +} + +private Attribute parseParameterDec(int st, int en, Vector entities, Vector types) +{ // should be att : Type + if (st+2 > en) { return null; } + + String attname = lexicals.get(st) + ""; + Type typ = parseType(st+2,en,entities,types); + if (typ == null) + { System.err.println("**** ERROR: Invalid/unknown type: " + showLexicals(st+2, en)); + return null; + } + Attribute att = new Attribute(attname, typ, ModelElement.INTERNAL); + att.setElementType(typ.getElementType()); + return att; +} + +private Attribute parseParameterDecInit(int st, int en, Vector entities, Vector types) +{ // can be att : Type = value + if (st + 2 > en) { return null; } + + String attname = lexicals.get(st) + ""; + for (int i = st+1; i < en; i++) + { String lex = lexicals.get(i) + ""; + if ("=".equals(lex)) + { Expression val = parse_expression(0,i+1,en); + Type typ = parseType(st+2,i-1,entities,types); + if (typ == null) + { System.err.println("**** ERROR: Invalid/unknown type: " + showLexicals(st+2, i-1)); + return null; + } + Attribute att = new Attribute(attname,typ,ModelElement.INTERNAL); + att.setInitialExpression(val); + return att; + } + } + Type tt = parseType(st+2,en,entities,types); + if (tt == null) + { System.err.println("**** ERROR: Invalid/unknown type: " + showLexicals(st+2, en)); + return null; + } + + Attribute newatt = new Attribute(attname,tt,ModelElement.INTERNAL); + return newatt; +} + + +public Vector parseAttributeDecs(int st, int en, Vector entities, Vector types) +{ // att1 : T1; att2 : T2; ... + + int st0 = st; + Vector res = new Vector(); + for (int k = st+2; k < en; k++) + { String lx = lexicals.get(k) + ""; + + if (lx.equals(":")) + { Attribute att = parseParameterDec(st0,k-3,entities,types); // k-2? + if (att != null) + { res.add(att); } + st0 = k-1; + } + } + + Attribute af = parseParameterDec(st0,en,entities,types); + if (af != null) + { res.add(af); } + return res; +} + + +public Vector parseAttributeDecs(Vector entities, Vector types) +{ int n = lexicals.size(); + return parseAttributeDecs(0,n-1,entities,types); +} + +public Vector parseAttributeDecsInit(int st, int en, Vector entities, Vector types) +{ // att1 : T1 = val1; att2 : T2 = val2; ... + + int st0 = st; + Vector res = new Vector(); + for (int k = st+2; k < en; k++) + { String lx = lexicals.get(k) + ""; + + if (lx.equals(":")) + { Attribute att = parseParameterDecInit(st0,k-3,entities,types); // k-2? + if (att != null) + { res.add(att); } + st0 = k-1; + } + } + + Attribute af = parseParameterDecInit(st0,en,entities,types); + if (af != null) + { res.add(af); } + return res; +} + + +public Vector parseAttributeDecsInit(Vector entities, Vector types) +{ int n = lexicals.size(); + return parseAttributeDecsInit(0,n-1,entities,types); +} + + /* public Expression parse_call_expression(int pstart, int pend) + { for (int i = pstart; i < pend; i++) + { String ss = lexicals.get(i) + ""; + if ("(".equals(ss)) + { Expression opref = parse_basic_expression(pstart,i-1); + if (opref == null) { return null; } + Vector args = parse_call_arguments(i+1,pend-1); + + if (opref instanceof BasicExpression) + { ((BasicExpression) opref).setParameters(args); } + // System.out.println("parsed call expression: " + opref); + return opref; + } + } + // System.out.println("Failed to parse call expression"); + return null; + } + + public Vector parse_call_arguments(int st, int ed) + { Vector res = new Vector(); + for (int i = st; i < ed; i++) + { String ss = lexicals.get(i) + ""; + if (",".equals(ss)) + { Expression e1 = parse_basic_expression(st,i-1); + res = parse_call_arguments(i+1,ed); + if (e1 != null) { res.add(0,e1); } + return res; + } + } + return res; + } */ + + + + + public Expression parse_bracketed_expression(int bcount, int pstart, int pend) + { if (lexicals.size() > 2 && + lexicals.get(pstart).toString().equals("(") && + lexicals.get(pend).toString().equals(")")) + { Expression eg = parse_expression(bcount+1, pstart+1, pend-1); + // System.out.println("parsed bracketed expression: " + eg); + if (eg != null) + { eg.setBrackets(true); } + return eg; + } + return null; + } // also case of pstart = (, pend-1 = ), pend.charAt(0) == '.' + + + + public Expression parse_ATLexpression(int bcount, int pstart, int pend, Vector entities, Vector types) + { Expression ee = null; + + if ("if".equals(lexicals.get(pstart) + "") && "endif".equals(lexicals.get(pend) + "")) + { ee = parse_ATLconditional_expression(bcount,pstart,pend,entities,types); + if (ee != null) { return ee; } + } + + if ("let".equals(lexicals.get(pstart) + "")) + { ee = parse_let_expression(bcount,pstart,pend,entities,types); + if (ee != null) { return ee; } + } + + if ("not".equals(lexicals.get(pstart) + "")) + { ee = parse_ATLexpression(bcount,pstart+1,pend,entities,types); + if (ee != null) + { return new UnaryExpression("not", ee); } + } + + OpOccurrence op = getBestOcc(pstart,pend); + if (op == null) // No logical ops here + { ee = parse_ATLeq_expression(bcount,pstart,pend,entities,types); + if (ee == null) + { ee = parse_ATLfactor_expression(bcount,pstart,pend,entities,types); } + return ee; + } + + if (op.bcount > bcount) // bracketed expression + { ee = parse_ATLeq_expression(bcount,pstart,pend,entities,types); + if (ee == null) + { ee = parse_ATLfactor_expression(bcount,pstart,pend,entities,types); } + return ee; + } + else + { ee = parse_ATLimplies_expression(bcount,pstart,pend,op.location,op.op,entities,types); } + return ee; + } + + public BinaryExpression parse_ATLimplies_expression(int bcount, int pstart, + int pend, int pos, String op, + Vector entities, Vector types) + { // There must be a logical operator at top level in the expression + Expression e1 = null; + Expression e2 = null; + // System.out.println("Trying to parse logical expression"); + // System.out.println("Trying at: " + pos + " " + op); + e1 = parse_ATLexpression(bcount,pstart,pos-1,entities,types); + + // if (e1 == null) + // { System.err.println("Invalid expression: " + showLexicals(pstart, pos-1)); } + + e2 = parse_ATLexpression(bcount,pos+1,pend,entities,types); + + // if (e2 == null) + // { System.err.println("Invalid expression: " + showLexicals(pos + 1, pend)); } + + if (e1 == null || e2 == null) + { System.out.println("Failed to parse: " + showLexicals(pstart, pend)); + return null; + } + else + { BinaryExpression ee = new BinaryExpression(op,e1,e2); + // System.out.println("Parsed implies expression: " + ee); + return ee; + } + } + + public Expression parse_ATLeq_expression(int bc, int pstart, + int pend, Vector entities, Vector types) + { Expression e1 = null; + Expression e2 = null; + + // System.out.println("Trying to parse eq. expression"); + + for (int i = pstart; i < pend; i++) + { + String ss = lexicals.elementAt(i).toString(); + if (ss.equals(":=") || ss.equals(":") || ss.equals("<:") || + ss.equals("/:") || ss.equals("/<:") || ss.equals("<>") || + Expression.comparitors.contains(ss)) + { e1 = parse_ATLadditive_expression(bc,pstart,i-1,entities,types); + e2 = parse_ATLadditive_expression(bc,i+1,pend,entities,types); + if (e1 == null || e2 == null) + { } // return null; } + else + { BinaryExpression ee = new BinaryExpression(ss,e1,e2); + // System.out.println("Parsed equality expression: " + ee); + return ee; + } + } + } + return parse_ATLadditive_expression(bc,pstart,pend,entities,types); + // return null; + } // <> is only for ATL + + public Expression parse_ATLadditive_expression(int bc, int pstart, int pend, Vector entities, Vector types) + { for (int i = pstart; i < pend; i++) + { String ss = lexicals.get(i).toString(); + if (ss.equals("+") || ss.equals("-") || ss.equals("\\/")) + { Expression e1 = parse_ATLfactor_expression(bc,pstart,i-1,entities,types); + Expression e2 = parse_ATLadditive_expression(bc,i+1,pend,entities,types); + if (e1 == null || e2 == null) + { } // return null; } + else + { BinaryExpression ee = new BinaryExpression(ss,e1,e2); + // System.out.println("Parsed additive expression: " + ee); + return ee; + } + } + } + return parse_ATLfactor_expression(bc,pstart,pend,entities,types); + } // reads left to right, not putting priorities on * above + + + public Expression parse_ATLfactor_expression(int bc, int pstart, int pend, Vector entities, Vector types) + { // System.out.println("Trying to parse factor expression"); + for (int i = pstart; i < pend; i++) + { String ss = lexicals.get(i).toString(); + if // (ss.equals("+") || ss.equals("-") || + (ss.equals("/\\") || ss.equals("^") || + ss.equals("*") || ss.equals("/") || ss.equals("div") || + ss.equals("mod")) + { Expression e1 = parse_ATLbasic_expression(bc,pstart,i-1,entities,types); // factor2 + Expression e2 = parse_ATLfactor_expression(bc,i+1,pend,entities,types); + if (e1 == null || e2 == null) + { } // return null; } + else + { BinaryExpression ee = new BinaryExpression(ss,e1,e2); + // System.out.println("Parsed factor expression: " + ee); + return ee; + } + } + } + return parse_ATLfactor2_expression(bc,pstart,pend,entities,types); + } // reads left to right, not putting priorities on * above + + // div is only for ATL. + + public Expression parse_ATLfactor2_expression(int bc, int pstart, int pend, Vector entities, Vector types) + { // System.out.println("Trying to parse factor2 expression from " + pstart + " to " + pend); + // case of argument->op() and left->op(right) + + for (int i = pend-1; pstart < i; i--) + { String ss = lexicals.get(i).toString(); + if (ss.equals("->") && "(".equals(lexicals.get(i+2) + "") && + ")".equals(lexicals.get(pend) + "")) + { String ss2 = lexicals.get(i+1).toString(); // must exist + if (i + 3 == pend && + ("any".equals(ss2) || "size".equals(ss2) || "isDeleted".equals(ss2) || + "display".equals(ss2) || "min".equals(ss2) || "max".equals(ss2) || + "sum".equals(ss2) || "sort".equals(ss2) || "asSet".equals(ss2) || + "sqrt".equals(ss2) || "sqr".equals(ss2) || "asSequence".equals(ss2) || + "last".equals(ss2) || "first".equals(ss2) || "closure".equals(ss2) || + "subcollections".equals(ss2) || "reverse".equals(ss2) || "prd".equals(ss2) || + "tail".equals(ss2) || "front".equals(ss2) || "isEmpty".equals(ss2) || + "notEmpty".equals(ss2) || "toUpperCase".equals(ss2) || "flatten".equals(ss2) || + "toLowerCase".equals(ss2) || "isInteger".equals(ss2) || "toLong".equals(ss2) || + "toInteger".equals(ss2) || "isReal".equals(ss2) || "toReal".equals(ss2) || + "exp".equals(ss2) || "log".equals(ss2) || "log10".equals(ss2) || + "sin".equals(ss2) || "cos".equals(ss2) || + "tan".equals(ss2) || "oclIsUndefined".equals(ss2) || + "floor".equals(ss2) || "ceil".equals(ss2) || "round".equals(ss2) || + "abs".equals(ss2) || "cbrt".equals(ss2) || "asin".equals(ss2) || + "acos".equals(ss2) || "atan".equals(ss2) || "isLong".equals(ss2) || + "sinh".equals(ss2) || "cosh".equals(ss2) || "tanh".equals(ss2)) ) + { Expression ee2 = parse_ATLfactor_expression(bc,pstart,i-1,entities,types); + if (ee2 == null) + { // System.err.println("Invalid unary -> expression at: " + showLexicals(pstart,pend)); + continue; + } + UnaryExpression ue = new UnaryExpression(ss+ss2,ee2); + // System.out.println("Parsed unary expression: " + ue); + return ue; // This excludes additional operators to the ones listed above. + } + else if ("exists".equals(ss2) && + i+5 < pend && // "(".equals(lexicals.get(i+2) + "") && + "|".equals(lexicals.get(i+4) + "") && + ")".equals(lexicals.get(pend) + "")) + { // It is ->exists(v|...) + Expression ee1 = parse_ATLexpression(bc+1,i+5,pend-1,entities,types); + if (ee1 == null) { continue; } + Expression ee2 = parse_ATLfactor_expression(bc,pstart,i-1,entities,types); + if (ee2 == null) { continue; } + BasicExpression bevar = + new BasicExpression(lexicals.get(i+3) + "",0); + BinaryExpression be = + new BinaryExpression("#",new BinaryExpression(":",bevar,ee2),ee1); + // System.out.println("Parsed: " + be); + return be; + } + else if (("exists1".equals(ss2) || "one".equals(ss2)) && + i+5 < pend && "|".equals(lexicals.get(i+4) + "") && + // "(".equals(lexicals.get(i+2) + "") && + ")".equals(lexicals.get(pend) + "")) + { // It is ->exists1(v|...) + Expression ee1 = parse_ATLexpression(bc+1,i+5,pend-1,entities,types); + if (ee1 == null) { continue; } + Expression ee2 = parse_ATLfactor_expression(bc,pstart,i-1,entities,types); + if (ee2 == null) { continue; } + BasicExpression bevar = + new BasicExpression(lexicals.get(i+3) + "",0); + BinaryExpression be = + new BinaryExpression("#1",new BinaryExpression(":",bevar,ee2),ee1); + // System.out.println("Parsed: " + be); + return be; + } + else if ("forAll".equals(ss2) && + i+5 < pend && "|".equals(lexicals.get(i+4) + "") && + // "(".equals(lexicals.get(i+2) + "") && + ")".equals(lexicals.get(pend) + "")) + { // It is ->forAll(v|...) + Expression ee1 = parse_ATLexpression(bc+1,i+5,pend-1,entities,types); + if (ee1 == null) { continue; } + Expression ee2 = parse_ATLfactor_expression(bc,pstart,i-1,entities,types); + if (ee2 == null) { continue; } + BasicExpression bevar = + new BasicExpression(lexicals.get(i+3) + "",0); + BinaryExpression be = + new BinaryExpression("!",new BinaryExpression(":",bevar,ee2),ee1); + // System.out.println("Parsed: " + be); + return be; + } + else if ("select".equals(ss2) && + i+5 < pend && "|".equals(lexicals.get(i+4) + "") && + // "(".equals(lexicals.get(i+2) + "") && + ")".equals(lexicals.get(pend) + "")) + { // It is ->select(v|...) + Expression ee1 = parse_ATLexpression(bc+1,i+5,pend-1,entities,types); + if (ee1 == null) { continue; } + Expression ee2 = parse_ATLfactor_expression(bc,pstart,i-1,entities,types); + if (ee2 == null) { continue; } + BasicExpression bevar = + new BasicExpression(lexicals.get(i+3) + "",0); + BinaryExpression be = + new BinaryExpression("|",new BinaryExpression(":",bevar,ee2),ee1); + // System.out.println("Parsed: " + be); + return be; + } + else if ("reject".equals(ss2) && + i+5 < pend && "|".equals(lexicals.get(i+4) + "") && + // "(".equals(lexicals.get(i+2) + "") && + ")".equals(lexicals.get(pend) + "")) + { // It is ->reject(v|...) + Expression ee1 = parse_ATLexpression(bc+1,i+5,pend-1,entities,types); + if (ee1 == null) { continue; } + Expression ee2 = parse_ATLfactor_expression(bc,pstart,i-1,entities,types); + if (ee2 == null) { continue; } + BasicExpression bevar = + new BasicExpression(lexicals.get(i+3) + "",0); + BinaryExpression be = + new BinaryExpression("|R",new BinaryExpression(":",bevar,ee2),ee1); + // System.out.println("Parsed: " + be); + return be; + } + else if ("collect".equals(ss2) && + i+5 < pend && "|".equals(lexicals.get(i+4) + "") && + // "(".equals(lexicals.get(i+2) + "") && + ")".equals(lexicals.get(pend) + "")) + { // It is ->collect(v|...) + Expression ee1 = parse_ATLexpression(bc+1,i+5,pend-1,entities,types); + if (ee1 == null) { continue; } + Expression ee2 = parse_ATLfactor_expression(bc,pstart,i-1,entities,types); + if (ee2 == null) { continue; } + BasicExpression bevar = + new BasicExpression(lexicals.get(i+3) + "",0); + BinaryExpression be = + new BinaryExpression("|C",new BinaryExpression(":",bevar,ee2),ee1); + // System.out.println("Parsed: " + be); + return be; + } + else if ("iterate".equals(ss2) && ";".equals(lexicals.get(i+4) + "") && i+7 < pend) + { String bevar = lexicals.get(i+3) + ""; + String acc = lexicals.get(i+5) + ""; + for (int h = i+7; h < pend; h++) + { String hs = lexicals.get(h) + ""; + if (hs.equals("=")) + { Type accType = parseType(i+7,h-1,entities,types); + for (int g = h+1; g < pend; g++) + { String gs = lexicals.get(g) + ""; + if (gs.equals("|")) + { Expression lft = parse_ATLexpression(bc,h+1,g-1,entities,types); + Expression rgt = parse_ATLexpression(bc,g+1,pend-1,entities,types); + if (lft != null && rgt != null) + { BinaryExpression resbe = new BinaryExpression("->iterate", lft, rgt); + resbe.iteratorVariable = bevar; + resbe.accumulator = new Attribute(acc,accType,ModelElement.INTERNAL); + return resbe; + } + } + } + } + } + } + else if (pend == i+3) // && "(".equals(lexicals.get(i+2) + "") && + // ")".equals(lexicals.get(pend) + "")) + { Expression ee2 = parse_ATLfactor_expression(bc,pstart,i-1,entities,types); + if (ee2 == null) { continue; } + UnaryExpression be = new UnaryExpression(ss+ss2,ee2); + // System.out.println("Parsed new unary -> expression: " + be); + return be; + } + else if (i + 3 <= pend) // && "(".equals(lexicals.get(i+2) + "") && + // ")".equals(lexicals.get(pend) + "")) + // this should allow new Binary operators + { // System.out.println("Tring tp parse at " + ss2); + Expression ee1 = parse_ATLexpression(bc+1,i+3,pend-1,entities,types); + if (ee1 == null) { continue; } + Expression ee2 = parse_ATLfactor_expression(bc,pstart,i-1,entities,types); + if (ee2 == null) { continue; } + BinaryExpression be = new BinaryExpression(ss+ss2,ee2,ee1); + // System.out.println("Parsed binary -> expression: " + be); + return be; + } + } + } + return parse_ATLbasic_expression(bc,pstart,pend,entities,types); + } // reads left to right, not putting priorities on * above + + + public Expression parse_ATLbasic_expression(int bc, int pstart, int pend, Vector entities, Vector types) + { // System.out.println("Trying tp parse basic expression from " + pstart + " to " + pend); + + if (pstart == pend) + { String ss = lexicals.elementAt(pstart).toString(); + if (invalidBasicExp(ss)) + { // System.err.println("ERROR: Invalid basic expression: " + ss); + return null; + } + + if (isKeyword(ss)) + { // System.err.println("ERROR: Invalid basic expression: keyword: " + ss); + return null; + } + + BasicExpression ee = // new BasicExpression(ss,0); // (ss) surely? + new BasicExpression(ss,0); + Expression ef = ee.checkIfSetExpression(); + + // if (ef instanceof BasicExpression) + // { ((BasicExpression) ef).setPrestate(ee.getPrestate()); } + + // System.out.println("Parsed basic expression: " + ss + " " + ee + " " + ef); + return ef; + } + + if (pstart < pend && "}".equals(lexicals.get(pend) + "") && + "Map".equals(lexicals.get(pstart) + "")) + { return parse_map_expression(bc,pstart+1,pend,entities,types); } + + if (pstart < pend && "}".equals(lexicals.get(pend) + "") && + "Sequence".equals(lexicals.get(pstart) + "") && + "{".equals(lexicals.get(pstart + 1) + "")) + { return parse_ATLsequence_expression(bc,pstart+1,pend,entities,types); } + + if (pstart < pend && "}".equals(lexicals.get(pend) + "") && + "Set".equals(lexicals.get(pstart) + "") && + "{".equals(lexicals.get(pstart + 1) + "")) + { return parse_ATLset_expression(bc,pstart+1,pend,entities,types); } + + if (pstart < pend && "-".equals(lexicals.get(pstart) + "")) + { Expression arg = parse_ATLadditive_expression(bc,pstart+1,pend,entities,types); + if (arg == null) + { // System.err.println("Not ATL additive expression: " + showLexicals(pstart+1, pend)); + return null; + } + return new UnaryExpression("-",arg); + } // likewise for "not" + + if (pstart + 1 < pend && ")".equals(lexicals.get(pend) + "") && + "(".equals(lexicals.get(pstart+1) + "")) + { Expression op = parse_ATLbasic_expression(bc,pstart,pstart,entities,types); + + Vector ve = parse_ATLfe_sequence(bc,pstart+2,pend-1,entities,types); + if (ve != null && op != null && op instanceof BasicExpression) // must be + { BasicExpression beop = (BasicExpression) op; + + if (Expression.isFunction(beop.data)) + { beop.umlkind = Expression.FUNCTION; } + else + { beop.setIsEvent(); } + + beop.setParameters(ve); + // System.out.println("Parsed call expression: " + beop); + return beop; + } + // return null; + } + + if (pstart + 2 < pend && ")".equals(lexicals.get(pend) + "") && + "(".equals(lexicals.get(pstart+2) + "") && + ("" + lexicals.get(pstart + 1)).charAt(0) == '.') + { Expression objref = parse_ATLbasic_expression(bc,pstart,pstart,entities,types); + String opstring = lexicals.get(pstart + 1) + ""; + String opstr = opstring.substring(1,opstring.length()); + + Vector ve = parse_ATLfe_sequence(bc,pstart+3,pend-1,entities,types); + if (ve != null && objref != null && objref instanceof BasicExpression) // must be + { BasicExpression beopref = (BasicExpression) objref; + BasicExpression beop = new BasicExpression(opstr); + + if (Expression.isFunction(opstr)) + { beop.umlkind = Expression.FUNCTION; } + else + { beop.setIsEvent(); } + + beop.setParameters(ve); + beop.setObjectRef(beopref); + // System.out.println("Parsed call expression: " + beop); + return beop; + } + // return null; + } + + if (pstart < pend && "]".equals(lexicals.get(pend) + "") && + "[".equals(lexicals.get(pstart+1) + "")) + { Expression op = parse_ATLbasic_expression(bc,pstart,pstart,entities,types); + Expression arg = parse_ATLfactor_expression(bc,pstart+2,pend-1,entities,types); + if (arg != null && op != null && op instanceof BasicExpression) // must be + { BasicExpression beop = (BasicExpression) op; + beop.setArrayIndex(arg); + // System.out.println("Parsed array expression: " + beop); + return beop; + } + // return null; + } + + if (pstart < pend && "]".equals(lexicals.get(pend-1) + "") && + "[".equals(lexicals.get(pstart+1) + "")) // be[arrind].be2 + { String tail = lexicals.get(pend) + ""; + if (tail.charAt(0) == '.') + { tail = tail.substring(1,tail.length()); } + Expression op = parse_ATLbasic_expression(bc,pstart,pstart,entities,types); + Expression arg = parse_ATLfactor_expression(bc,pstart+2,pend-2,entities,types); + if (arg == null) + { System.err.println("Invalid ATL array argument: " + showLexicals(pstart+2,pend-2)); } + else if (op != null && op instanceof BasicExpression) // must be + { BasicExpression beop = (BasicExpression) op; + beop.setArrayIndex(arg); + BasicExpression te = new BasicExpression(tail); + BasicExpression ef = (BasicExpression) te.checkIfSetExpression(); + if (ef != null) + { ef.setInnerObjectRef(beop); } + // System.out.println("Parsed array 1 expression: " + ef); + return ef; + } + // return null; + } + + if (pstart + 1 < pend && ")".equals(lexicals.get(pend) + "") && + !("(".equals(lexicals.get(pstart) + ""))) + { for (int i = pstart + 1; i < pend; i++) + { String strs = lexicals.get(i) + ""; + if ("(".equals(strs)) + { Expression op = parse_ATLbasic_expression(bc, pstart, i-1,entities,types); + if (op != null && op instanceof BasicExpression) + { Vector ve = parse_ATLfe_sequence(bc,i+1,pend-1,entities,types); + if (ve != null) + { BasicExpression beop = (BasicExpression) op; + beop.setIsEvent(); + beop.setParameters(ve); + // System.out.println("Parsed extended call expression " + beop); + return beop; + } + } + } + } + } + + + String ttail = lexicals.get(pend) + ""; + if (ttail.charAt(0) == '.') + { ttail = ttail.substring(1,ttail.length()); + BasicExpression op = new BasicExpression(ttail); + + Expression arg = parse_ATLexpression(bc,pstart,pend-1,entities,types); + if (arg != null) + { op.setObjectRef(arg); + return op; + } + } + + return parse_ATLbracketed_expression(bc,pstart,pend,entities,types); + } + + public Expression parse_ATLbracketed_expression(int bcount, int pstart, int pend, Vector entities, Vector types) + { if (lexicals.size() > 2 && + lexicals.get(pstart).toString().equals("(") && + lexicals.get(pend).toString().equals(")")) + { Expression eg = parse_ATLexpression(bcount+1, pstart+1, pend-1,entities,types); + // System.out.println("parsed bracketed expression: " + eg); + if (eg != null) + { eg.setBrackets(true); } + return eg; + } + return null; + } // also case of pstart = (, pend-1 = ), pend.charAt(0) == '.' + + + + + public Expression parse_ATLset_expression(int bc,int pstart,int pend, Vector entities, Vector types) + { Vector ve = parse_ATLfe_sequence(bc,pstart+1,pend-1,entities,types); + if (ve == null) + { return null; } + Expression res = new SetExpression(ve,false); + // System.out.println("Parsed set expression: " + res); + return res; + } + + public Expression parse_ATLsequence_expression(int bc,int pstart,int pend, Vector entities, Vector types) + { Vector ve = parse_ATLfe_sequence(bc,pstart+1,pend-1,entities,types); + if (ve == null) + { return null; } + Expression res = new SetExpression(ve,true); + // System.out.println("Parsed sequence expression: " + res); + return res; + } + + + public Vector parse_ATLfe_sequence(int bc, int st, int ed, Vector entities, Vector types) + { Vector res = new Vector(); + // if (st == ed) // just one basic exp + // { Expression elast = parse_basic_expression(bc,st,ed); + // res.add(elast); + // return res; + // } + if (st > ed) + { return res; } + return getATL_FESeq(bc,st,ed,entities,types); + + // Only commas at the top level of the expression are wanted! + } + + private Vector getATL_FESeq(int bc, int st, int en, Vector entities, Vector types) + { // Scans the lexicals inside the outer brackets of + // a potential fe-sequence + + int bcnt = 0; int sqbcnt = 0; int cbcnt = 0; + Vector res = new Vector(); + int st0 = st; + String buff = ""; + for (int i = st; i <= en; i++) + { String lx = lexicals.get(i) + ""; + buff = buff + lx; + if ("(".equals(lx)) { bcnt++; } + else if (")".equals(lx)) + { bcnt--; + if (bcnt < 0) { return null; } + } + else if ("[".equals(lx)) { sqbcnt++; } + else if ("]".equals(lx)) { sqbcnt--; } + else if ("{".equals(lx)) { cbcnt++; } + else if ("}".equals(lx)) { cbcnt--; } + else if (",".equals(lx)) + { if (bcnt == 0 && sqbcnt == 0 && cbcnt == 0) + { // top-level , + Expression exp = parse_ATLadditive_expression(bc,st0,i-1,entities,types); + if (exp == null) + { // System.out.println("Invalid ATL additive exp: " + buff); + return null; + } + res.add(exp); + st0 = i + 1; + buff = ""; + } + } + } + // at the end: + if (bcnt == 0 && sqbcnt == 0 && cbcnt == 0) + { Expression exp = parse_ATLadditive_expression(bc,st0,en,entities,types); + if (exp == null) + { // System.out.println("Invalid ATL additive exp: " + buff); + return null; + } + res.add(exp); + } + else + { System.err.println("Not ATL fe sequence: " + showLexicals(st,en)); + return null; + } + return res; + } + + + /* public Statement parseStatement(Vector entities, Vector types) + { int en = lexicals.size(); + return parseStatement(0,en-1,entities,types); + } */ + + + + public Statement parseStatement(int s, int e, Vector entities, Vector types) + { Statement st = parseSequenceStatement(s,e, entities, types); + if (st == null) + { st = parseLoopStatement(s,e, entities, types); } + if (st == null) + { st = parseConditionalStatement(s,e, entities, types); } + if (st == null) + { st = parseBasicStatement(s,e, entities, types); } + return st; + } + + + public Statement parseSequenceStatement(int s, int e, Vector entities, Vector types) + { Statement s1 = null; + Statement s2 = null; + for (int i = s; i < e; i++) + { String ss = lexicals.get(i) + ""; + if (ss.equals(";")) + { s1 = parseStatement(s,i-1, entities,types); + s2 = parseStatement(i+1,e, entities,types); + if (s1 == null || s2 == null) { continue; } // try another ; + // { return null; } + else + { SequenceStatement res = new SequenceStatement(); + res.addStatement(s1); + res.addStatement(s2); + // System.out.println("Parsed ; statement: " + res); + return res; + } + } + } + return null; + } + + public Statement parseLoopStatement(int s, int e, Vector entities, Vector types) + { if ("for".equals(lexicals.get(s) + "")) + { Statement s1 = null; + Expression test = null; + for (int i = s+1; i < e; i++) + { String ss = lexicals.get(i) + ""; + if (ss.equals("do")) + { test = parse_expression(0,s+1,i-1); + if (test == null) + { System.err.println("ERROR: Invalid test in for loop: " + showLexicals(s+1,i-1)); } + s1 = parseStatement(i+1, e, entities, types); + if (s1 == null || test == null) + { return null; } + WhileStatement res = new WhileStatement(test,s1); + res.setLoopKind(Statement.FOR); + if (test instanceof BinaryExpression) + { BinaryExpression betest = (BinaryExpression) test; + if (":".equals(betest.getOperator())) + { res.setLoopRange(betest.getLeft(), betest.getRight()); } + } + // System.out.println("Parsed for statement: " + res); + return res; + } + } + // System.err.println("Unable to parse for statement: " + lexicals.get(s) + " ... " + + // lexicals.get(e)); + } + else if ("while".equals(lexicals.get(s) + "")) + { Statement s1 = null; + Expression test = null; + for (int i = s+1; i < e; i++) + { String ss = lexicals.get(i) + ""; + if (ss.equals("do")) + { test = parse_expression(0,s+1,i-1); + if (test == null) + { System.err.println("ERROR: Invalid test in while loop: " + showLexicals(s+1,i-1)); } + s1 = parseStatement(i+1, e, entities, types); + if (s1 == null || test == null) + { return null; } + WhileStatement res = new WhileStatement(test,s1); + res.setLoopKind(Statement.WHILE); + // System.out.println("Parsed while statement: " + res); + return res; + } + } + // System.err.println("Unable to parse while statement: " + lexicals.get(s) + " ... " + + // lexicals.get(e)); + } + return null; + } + + public Statement parseConditionalStatement(int s, int e, Vector entities, Vector types) + { if ("if".equals(lexicals.get(s) + "")) + { Statement s1 = null; + Statement s2 = null; + Expression test = null; + for (int i = s+1; i < e; i++) + { String ss = lexicals.get(i) + ""; + if (ss.equals("then")) + { test = parse_expression(0,s+1,i-1); + if (test == null) + { System.err.println("ERROR: Invalid test in conditional: " + showLexicals(s+1,i-1)); + continue; + } + + for (int j = i+1; j < e; j++) + { String ss1 = lexicals.get(j) + ""; + if (ss1.equals("else")) + { s1 = parseStatement(i+1, j-1, entities, types); + s2 = parseBasicStatement(j+1,e, entities, types); // else must be bracketed or basic + if (s1 == null || s2 == null || test == null) + { continue; } + + IfStatement res = new IfStatement(test,s1,s2); + // System.out.println("Parsed if statement: " + res); + return res; + } + } + } + } + // System.err.println("Unable to parse if-then-else statement: " + showLexicals(s,e)); + } + return null; + } // no option for if-then without else. + + + + public Statement parseBasicStatement(int s, int e, Vector entities, Vector types) + { if (e == s) + { if ("skip".equals(lexicals.get(e) + "")) + { return new InvocationStatement("skip",null,null); } + // operation call + else if ("return".equals(lexicals.get(e) + "")) + { return new ReturnStatement(); } + else + { Expression ee = parse_basic_expression(0,s,e); + if (ee == null) + { // System.err.println("Invalid basic expression: " + showLexicals(s,e)); + return null; + } + InvocationStatement istat = new InvocationStatement(ee + "",null,null); + istat.setCallExp(ee); + return istat; + } // what about continue and break? + } + + if ("(".equals(lexicals.get(s) + "") && + ")".equals(lexicals.get(e) + "")) + { Statement stat = parseStatement(s+1,e-1,entities,types); + if (stat != null) + { stat.setBrackets(true); } + return stat; + } // set brackets + else if ("return".equals(lexicals.get(s) + "")) + { Expression ret = parse_expression(0,s+1,e); + if (ret != null) + { return new ReturnStatement(ret); } + } + else if ("execute".equals(lexicals.get(s) + "")) + { Expression ret = parse_expression(0,s+1,e); + if (ret != null) + { return new ImplicitInvocationStatement(ret); } + } + else if ("var".equals(lexicals.get(s) + "")) + { // creation with complex type + String varname = lexicals.get(s+1) + ""; + Type typ = parseType(s+3,e,entities,types); + CreationStatement cs = new CreationStatement(typ + "", varname); + cs.setType(typ); + if (typ != null) + { cs.setElementType(typ.getElementType()); } + return cs; + } + else if (e == s + 2 && ":".equals(lexicals.get(s+1) + "")) + { CreationStatement cs = new CreationStatement(lexicals.get(e) + "", lexicals.get(s) + ""); + Type tt = Type.getTypeFor(lexicals.get(e) + "", new Vector(), new Vector()); // assume primitive + cs.setType(tt); + return cs; + } // allow any type + else + { for (int i = s; i < e; i++) + { String ss = lexicals.get(i) + ""; + if (":=".equals(ss)) + { if (i == s + 3 && ":".equals(lexicals.get(s + 1) + "")) + { // Assignment with declaration + Type t = Type.getTypeFor(lexicals.get(s + 2) + "", new Vector(), new Vector()); + String var = lexicals.get(s) + ""; + Expression exp2 = parse_expression(0,i+1,e); + if (exp2 == null) { return null; } + /* System.out.println("Parsed assignment with type: " + var + " : " + + t + " := " + exp2); */ + AssignStatement ast = new AssignStatement(new BasicExpression(var), exp2); + ast.setType(t); + ast.setOperator(":="); + return ast; + } + Expression e1 = parse_basic_expression(0,s,i-1); + Expression e2 = parse_expression(0,i+1,e); + if (e1 == null || e2 == null) + { // System.err.println("ERROR: Unable to parse basic command: " + showLexicals(s,e)); + return null; + } + // System.out.println("Parsed assignment: " + e1 + " := " + e2); + AssignStatement res = new AssignStatement(e1,e2); + res.setOperator(":="); + return res; + } + } + } // all of these should use parseType to allow general types. + // should allow v : T := e with general type T + + Expression ee = parse_basic_expression(0,s,e); + if (ee != null) + { InvocationStatement istat = new InvocationStatement(ee + "",null,null); + istat.setCallExp(ee); + return istat; + } + + // System.out.println("ERROR: Unable to parse basic command: " + showLexicals(s,e)); + return null; + } + + public Statement parseStatement(Vector entities, Vector types) + { Vector stats = splitIntoStatementSequence(0,0,lexicals.size()-1, entities, types); + // System.out.println("TOP LEVEL STATEMENTS ARE: " + stats); + + if (stats == null) + { return null; } + + if (stats.size() == 0) + { return new SequenceStatement(); } + else if (stats.size() == 1) + { return (Statement) stats.get(0); } + else + { return new SequenceStatement(stats); } + } + + public Vector splitIntoStatementSequence(int bc, int s, int e, Vector entities, Vector types) + { Vector res = new Vector(); + int bcc = bc; + boolean instring = false; + + if (s >= e) + { return res; } + + Statement s1 = null; + Vector s2 = new Vector(); + + for (int i = s; i < e; i++) + { String ss = lexicals.get(i) + ""; + if (ss.equals(";") && bcc == bc && !instring) + { s1 = parseStatement(s,i-1,entities,types); + if (s1 == null) + { System.err.println("WARNING: unrecognised statement: " + showLexicals(s,i-1)); + continue; + } + else + { s2 = splitIntoStatementSequence(bc,i+1,e,entities,types); } + if (s2 == null) + { continue; } // try another ; + else + { res.add(s1); + res.addAll(s2); + // System.out.println("Parsed ; statement: " + res); + return res; + } + } + else if ("(".equals(ss) && !instring) // and not inside a string + { bcc++; } + else if (")".equals(ss) && !instring) + { bcc--; } + else if ("\"".equals(ss) && !instring) // and not inside a string + { instring = true; } + else if ("\"".equals(ss) && instring) + { instring = false; } + } + + Statement ls = parseStatement(s,e,entities,types); + if (ls != null) + { res.add(ls); } + return res; + } + + + + public Vector parseKM3(Vector entities, Vector types, Vector gens, Vector pasts) + { Vector res = new Vector(); + int en = lexicals.size()-1; + + // retain the package name, it becomes the system name. + int prevstart = 0; + for (int i = 0; i < en; i++) + { String lex = lexicals.get(i) + ""; + if ("package".equals(lex)) + { prevstart = i; + break; + } + } + + int st = prevstart; + + for (int i = st+1; i < en; i++) + { String lex = lexicals.get(i) + ""; + if ("package".equals(lex)) + { // parse contents of previous package: + Vector resp = parseKM3package(prevstart,i-1,entities,types,gens,pasts); + res.addAll(resp); + prevstart = i; + } + } + + Vector resp = parseKM3package(prevstart,en-1,entities,types,gens,pasts); + res.addAll(resp); + return res; + } + + public UseCase parseKM3UseCase(Vector entities, Vector types, + Vector gens, Vector pasts) + { int en = lexicals.size()-1; + return parseKM3UseCase(0,en,entities,types,gens,pasts); + } + + + public Vector parseKM3package(int st, int en, + Vector entities, Vector types, Vector gens, Vector pasts) + { Vector res = new Vector(); + if ("package".equals(lexicals.get(st) + "") && + "{".equals(lexicals.get(st+2) + "")) + { String pname = lexicals.get(st+1) + ""; + System.out.println("Parsing package " + pname); + + for (int i = st+3; i < en; i++) + { String lx = lexicals.get(i) + ""; + if ("class".equals(lx) || "abstract".equals(lx) || "enumeration".equals(lx) || + "interface".equals(lx) || "datatype".equals(lx) || "usecase".equals(lx)) + { Vector v = parseKM3PackageContents(i,en-1,entities,types,gens,pasts); + res.addAll(v); + return res; + } + } + } + return res; + } + + + public Vector parseKM3PackageContents(int st, int en, Vector entities, + Vector types, Vector gens, Vector pasts) + { Vector res = new Vector(); + if (st >= en) + { return res; } + for (int i = st + 2; i <= en; i++) + { String lx = lexicals.get(i) + ""; + if ("class".equals(lx) || "abstract".equals(lx) || "enumeration".equals(lx) || + "interface".equals(lx) || "datatype".equals(lx) || "usecase".equals(lx)) + { Object e = parseKM3classifier(st,i-1,entities,types,gens,pasts); + if (e != null && e instanceof Type) + { types.add(e); } + // else if (e != null && e instanceof Entity && "interface".equals(lx)) + // { ((Entity) e).setInterface(true); } + res = parseKM3PackageContents(i,en,entities,types,gens,pasts); + if (e != null) { res.add(0,e); } + return res; + } + } + + Object e1 = parseKM3classifier(st,en,entities,types,gens,pasts); + if (e1 != null) + { res.add(e1); + if (e1 instanceof Type) + { types.add(e1); } + // else if (e1 != null && e1 instanceof Entity && "interface".equals(lx)) + // { ((Entity) e1).setInterface(true); } + } + + return res; + } + + public Object parseKM3classifier(Vector entities, Vector types, + Vector gens, Vector pasts) + { return parseKM3classifier(0, lexicals.size()-1, entities, types, gens, pasts); } + + + public Object parseKM3classifier(int st, int en, Vector entities, Vector types, + Vector gens, Vector pasts) + { boolean abstr = false; + boolean interf = false; + String rname = ""; + int start = st; + Vector atts = new Vector(); + Vector roles = new Vector(); + + String lx = lexicals.get(st) + ""; + + if ("abstract".equals(lx) && + "class".equals(lexicals.get(st + 1) + "") && + "}".equals(lexicals.get(en) + "")) + { abstr = true; + start = st + 3; + rname = lexicals.get(st + 2) + ""; + } + else if ("interface".equals(lx) && + "}".equals(lexicals.get(en) + "")) + { interf = true; + start = st + 2; + rname = lexicals.get(st + 1) + ""; + } + else if ("class".equals(lx) && + "}".equals(lexicals.get(en) + "")) + { abstr = false; + interf = false; + start = st + 2; + rname = lexicals.get(st + 1) + ""; + } + else if ("datatype".equals(lx)) + { return new Type(lexicals.get(st + 1) + "", null); } + else if ("enumeration".equals(lx)) + { int j = st + 2; + Vector values = new Vector(); + while (j < en) + { if ("literal".equals(lexicals.get(j) + "")) + { values.add(lexicals.get(j+1) + ""); + j = j + 2; + } + else + { j++; } + } + Type tt = new Type(lexicals.get(st + 1) + "", values); + return tt; + } + else if ("usecase".equals(lx)) + { return parseKM3UseCase(st, en, entities, types, gens, pasts); } + else + { return null; } + + String supr = ""; + + if ("extends".equals(lexicals.get(start) + "")) + { supr = lexicals.get(start+1) + ""; + int p = start + 1; + PreGeneralisation pregen = new PreGeneralisation(); + pregen.e1name = rname; + pregen.e2name = supr; + gens.add(pregen); // to be linked in UCDArea. + + p++; + if ((lexicals.get(p) + "").equals("{")) + { start = p+1; } + else + { while (!(lexicals.get(p) + "").equals("{")) + { supr = lexicals.get(p+1) + ""; // multiple inheritance: extends C1, C2 { + PreGeneralisation pregen2 = new PreGeneralisation(); + pregen2.e1name = rname; + pregen2.e2name = supr; + System.err.println("Warning: multiple inheritance for " + rname); + gens.add(pregen2); // to be linked in UCDArea. + p = p+1; + } + start = p + 1; + } + } + else + { start = start + 1; } + + + Entity res = new Entity(rname); + res.setCardinality("*"); + + if (abstr) + { res.setAbstract(true); } + if (interf) + { res.setInterface(true); } + entities.add(res); + + System.out.println(">>> Parsing KM3 class " + rname); + + int reached = start; // start of the next element to be parsed. reached <= i + + for (int i = start + 3; i < en; i++) + { String lx2 = lexicals.get(i) + ""; + if ("attribute".equals(lx2) || "reference".equals(lx2) || "operation".equals(lx2) || + "query".equals(lx2) || "static".equals(lx2)) + { String lxr = lexicals.get(reached) + ""; + if ("attribute".equals(lxr) || "reference".equals(lxr) || "query".equals(lxr) || + "operation".equals(lxr) || "static".equals(lxr)) + { if ("static".equals(lxr)) + { if ("attribute".equals(lexicals.get(reached+1) + "")) + { Attribute attr = parseAttributeClause(reached+1, i - 1, entities, types); + if (attr == null) + { System.err.println("!! Cannot parse attribute " + + lexicals.get(reached + 2)); + } + else + { atts.add(attr); + attr.setStatic(true); + res.addAttribute(attr); + } + } + else if ("operation".equals(lexicals.get(reached+1) + "") || + "query".equals(lexicals.get(reached+1) + "")) + { BehaviouralFeature bf = + operationDefinition(reached + 2, i-2, entities, types); + if (bf != null) + { bf.setStatic(true); + res.addOperation(bf); + } + else + { System.err.println("!! ERROR: Invalid operation definition: " + + showLexicals(reached+2, i-2)); + } + } + } + else if ("attribute".equals(lxr)) + { Attribute attr = parseAttributeClause(reached, i - 1, entities, types); + if (attr == null) + { System.err.println("!! Cannot parse attribute " + + lexicals.get(reached + 1)); + } + else + { atts.add(attr); + res.addAttribute(attr); + } + } + else if ("reference".equals(lxr)) + { PreAssociation ast = parseAssociationClause(reached, i-1, entities, types); + if (ast == null) + { System.err.println("!! Cannot parse reference " + + lexicals.get(reached + 1)); + } + else + { ast.e1name = rname; + pasts.add(ast); + } + // res.addAssociation(ast); + } + else if ("operation".equals(lxr) || "query".equals(lxr)) + { BehaviouralFeature bf = + operationDefinition(reached + 1, i-2, entities, types); + if (bf != null) + { res.addOperation(bf); } + else + { System.err.println("ERROR: Invalid operation definition: " + + showLexicals(reached+1,i-2)); + } + } + reached = i; // one element has been parsed, go on to start of next one. + } + else + { reached = i; + i++; + } + if ("static".equals(lx2)) { i++; } // don't test the next keyword. + } + } + + if (reached + 3 < en - 1) + { boolean isStatic = false; + + if ("static".equals(lexicals.get(reached) + "")) + { isStatic = true; + reached = reached + 1; + } + + if ("attribute".equals(lexicals.get(reached) + "")) + { Attribute aa = parseAttributeClause(reached, en-1, entities, types); + if (aa == null) + { System.err.println("!! Cannot parse attribute " + + lexicals.get(reached + 1)); + } + else + { aa.setStatic(isStatic); + atts.add(aa); + res.addAttribute(aa); + } + } + else if ("reference".equals(lexicals.get(reached) + "")) + { PreAssociation ast = parseAssociationClause(reached, en-1, entities, types); + if (ast == null) + { System.err.println("!! Cannot parse reference " + + lexicals.get(reached + 1)); + } + else + { ast.e1name = rname; + pasts.add(ast); + } + // res.addAssociation(ast); + } + else if ("operation".equals(lexicals.get(reached) + "") || + "query".equals(lexicals.get(reached) + "")) + { BehaviouralFeature bf = + operationDefinition(reached + 1, en-2, entities, types); + if (bf != null) + { bf.setStatic(isStatic); + res.addOperation(bf); + } + else + { System.err.println("!! ERROR: Invalid operation definition: " + + showLexicals(reached+1,en-2)); + } + } + + } + + return res; + } + + public UseCase parseKM3UseCase(int st, int en, Vector entities, Vector types, + Vector gens, Vector pasts) + { // usecase name { postconditions } + String nme = lexicals.get(st+1) + ""; + + UseCase uc = new UseCase(nme); + + for (int i = st + 2; i < en; i++) + { String lx = lexicals.get(i) + ""; + if (":".equals(lx) && ":".equals(lexicals.get(i+1) + "")) + { String scope = lexicals.get(i-1) + ""; // must be present, can be void + Entity ent = (Entity) ModelElement.lookupByName(scope, entities); + + for (int j = i+2; j < en; j++) + { if (":".equals(lexicals.get(j) + "") && ":".equals(lexicals.get(j+1) + "")) + { Expression ee = parse_expression(0, i+2, j-2); + System.out.println(">>>> Parsed use case postcondition " + ee); + + if (ee != null && (ee instanceof BinaryExpression)) + { BinaryExpression be = (BinaryExpression) ee; + if ("=>".equals(be.operator)) + { Constraint con = new Constraint(be.left,be.right); + con.setOwner(ent); + uc.addPostcondition(con); + con.setUseCase(uc); + } + else + { Constraint cc = new Constraint(new BasicExpression(true), ee); + cc.setOwner(ent); + uc.addPostcondition(cc); + cc.setUseCase(uc); + } + } + else if (ee != null) + { Constraint cc = new Constraint(new BasicExpression(true), ee); + cc.setOwner(ent); + uc.addPostcondition(cc); + cc.setUseCase(uc); + } + j = en; + } + else if (j == en-1) // the closing } + { Expression ff = parse_expression(0, i+2, j); + System.out.println(">>>> Parsed final use case postcondition " + ff); + if (ff != null && (ff instanceof BinaryExpression)) + { BinaryExpression fe = (BinaryExpression) ff; + if ("=>".equals(fe.operator)) + { Constraint con = new Constraint(fe.left,fe.right); + con.setOwner(ent); + uc.addPostcondition(con); + con.setUseCase(uc); + } + else + { Constraint cc = new Constraint(new BasicExpression(true), ff); + cc.setOwner(ent); + uc.addPostcondition(cc); + cc.setUseCase(uc); + } + } + else if (ff != null) + { Constraint cc = new Constraint(new BasicExpression(true), ff); + cc.setOwner(ent); + uc.addPostcondition(cc); + cc.setUseCase(uc); + } + j = en; + } + } + } + } + + return uc; + } + + public Attribute parseAttributeClause(int st, int en, Vector entities, Vector types) + { // attribute name [stereotypes] : type ; + + String nme = lexicals.get(st+1) + ""; + + for (int i = st+2; i < en; i++) + { if (":".equals(lexicals.get(i) + "")) + { Type typ = parseType(i+1,en-1,entities,types); + if (typ != null) + { Attribute att = new Attribute(nme,typ,ModelElement.INTERNAL); + att.setElementType(typ.getElementType()); + + for (int j = st+2; j < i; j++) + { String lx = lexicals.get(j) + ""; + if ("identity".equals(lx)) + { att.stereotypes.add("identity"); + att.setIdentity(true); + } + else if ("static".equals(lx)) + { att.stereotypes.add("static"); + att.setStatic(true); + } + } + return att; + } + } + } + return null; + } + + public PreAssociation parseAssociationClause(int st, int en, Vector entities, Vector types) + { // reference role2 [cards] [stereotypes] : Entity2 [opp] ; + + PreAssociation res = new PreAssociation(); + res.role2 = lexicals.get(st+1) + ""; + res.card2 = ModelElement.ONE; // default + int reached = st+2; + for (int i = st+2; i < en; i++) + { if (":".equals(lexicals.get(i) + "")) + { String tt = lexicals.get(i+1) + ""; + res.e2name = tt; + for (int j = st+2; j < i; j++) + { String lx = lexicals.get(j) + ""; + if ("ordered".equals(lx)) + { res.stereotypes.add("ordered"); } + else if ("container".equals(lx)) + { res.stereotypes.add("aggregation"); } + else if ("[".equals(lx)) + { if ("*".equals(lexicals.get(j+1) + "")) + { // upper and lower are MANY + res.card2 = ModelElement.MANY; + } + else if ("0".equals(lexicals.get(j+1) + "") && j+3 <= i && + "-".equals(lexicals.get(j+2) + "") && + "1".equals(lexicals.get(j+3) + "")) + { res.card2 = ModelElement.ZEROONE; } + else if ("1".equals(lexicals.get(j+1) + "") && j+2 <= i && + "-".equals(lexicals.get(j+2) + "")) + { res.card2 = ModelElement.MANY; } + else if (j+2 <= i && "-".equals(lexicals.get(j+2) + "")) + { res.card2 = ModelElement.MANY; } + else + { res.card2 = ModelElement.ONE; } + } + } + reached = i+2; + } + } + + if (";".equals(lexicals.get(reached) + "")) + { return res; } + else if ("oppositeOf".equals(lexicals.get(reached) + "")) + { res.role1 = lexicals.get(reached+1) + ""; + return res; + } + return res; + } + + // public Statement parseATLStatement() + // { return parseATLStatement(0, lexicals.size() - 1, new Vector(), new Vector()); } + + public Statement parseATLStatement(int s, int e, Vector entities, Vector types) + { Statement st = parseATLSequenceStatement(s,e,entities,types); + if (st == null) + { st = parseATLLoopStatement(s,e,entities,types); } + if (st == null) + { st = parseATLConditionalStatement(s,e,entities,types); } + if (st == null && ";".equals(lexicals.get(e) + "")) + { st = parseATLBasicStatement(s,e-1,entities,types); } + return st; + } + + + public Statement parseATLSequenceStatement(int s, int e, Vector entities, Vector types) + { Statement s1 = null; + Statement s2 = null; + for (int i = s; i < e; i++) + { String ss = lexicals.get(i) + ""; + if (ss.equals(";") || ss.equals("}")) + { s1 = parseATLStatement(s,i,entities,types); + s2 = parseATLStatement(i+1,e,entities,types); + if (s1 == null || s2 == null) { continue; } // try another ; + // { return null; } + else + { SequenceStatement res = new SequenceStatement(); + res.addStatement(s1); + res.addStatement(s2); + // System.out.println("Parsed ATL sequence statement: " + res); + return res; + } + } + } + return null; + } + + public Statement parseATLLoopStatement(int s, int e, Vector entities, Vector types) + { if ("for".equals(lexicals.get(s) + "") && + "in".equals(lexicals.get(s+3) + "")) + { Statement s1 = null; + Expression test = null; + for (int i = s+1; i < e; i++) + { String ss = lexicals.get(i) + ""; + if (ss.equals("{") && "}".equals(lexicals.get(e) + "")) + { Expression var = parse_ATLexpression(0,s+2,s+2,entities,types); + Expression range = parse_ATLexpression(0,s+4,i-2,entities,types); + s1 = parseATLStatement(i+1, e-1,entities,types); + if (var == null || range == null || s1 == null) + { return null; } + test = new BinaryExpression(":",var,range); + WhileStatement res = new WhileStatement(test,s1); + res.setLoopKind(Statement.FOR); + res.setLoopRange(var, range); + // System.out.println("Parsed ATL for statement: " + res); + return res; + } + } + } + else if ("while".equals(lexicals.get(s) + "")) + { Statement s1 = null; + Expression test = null; + for (int i = s+1; i < e; i++) + { String ss = lexicals.get(i) + ""; + if (ss.equals("{")) + { test = parse_ATLexpression(0,s+1,i-1,entities,types); + s1 = parseATLStatement(i+1, e,entities,types); + if (s1 == null || test == null) + { return null; } + WhileStatement res = new WhileStatement(test,s1); + res.setLoopKind(Statement.WHILE); + // System.out.println("Parsed ATL while statement: " + res); + return res; + } + } + } + return null; + } + + public Statement parseATLConditionalStatement(int s, int e, Vector entities, Vector types) + { if ("if".equals(lexicals.get(s) + "")) + { Statement s1 = null; + Statement s2 = null; + Expression test = null; + for (int i = s+1; i < e; i++) + { String ss = lexicals.get(i) + ""; + if (ss.equals("{") && "}".equals(lexicals.get(e) + "")) + { test = parse_ATLexpression(0,s+1,i-1,entities,types); + if (test == null) { continue; } + + for (int j = i+1; j < e; j++) + { String ss1 = lexicals.get(j) + ""; + if (ss1.equals("else") && "{".equals(lexicals.get(j+1) + "")) + { s1 = parseATLStatement(i+1, j-2,entities,types); + s2 = parseATLStatement(j+2, e-1,entities,types); + if (s1 == null || s2 == null || test == null) + { continue; } + IfStatement res = new IfStatement(test,s1,s2); + // System.out.println("Parsed ATL if statement: " + res); + return res; + } + } + s1 = parseATLStatement(i+1,e-1,entities,types); + if (s1 != null) + { return new IfStatement(test,s1); } + } + } + } + return null; + } + + public Statement parseATLBasicStatement(int s, int e, Vector entities, Vector types) + { if (e == s) + { if ("skip".equals(lexicals.get(e) + "")) + { return new InvocationStatement("skip",null,null); } + // operation call + else if ("return".equals(lexicals.get(e) + "")) + { return new ReturnStatement(); } + else + { Expression ee = parse_ATLbasic_expression(0,s,e,entities,types); + InvocationStatement istat = new InvocationStatement(ee + "",null,null); + istat.setCallExp(ee); + return istat; + } + } + else if ("return".equals(lexicals.get(s) + "")) + { Expression ret = parse_ATLexpression(0,s+1,e,entities,types); + if (ret != null) + { return new ReturnStatement(ret); } + else + { System.err.println("Invalid expression in return: " + showLexicals(s+1,e)); } + } + else if ("var".equals(lexicals.get(s) + "")) // for ETL + { Expression lft = parse_ATLbasic_expression(0,s+1,s+1,entities,types); + if ("new".equals(lexicals.get(s+3) + "")) + { // var v = new E() in ETL + Type tt = parseType(s+4,e-2,entities,types); + if (tt != null) + { CreationStatement cr = new CreationStatement(tt.getName(), lft + ""); + cr.setType(tt); + return cr; + } + } + Expression rgt = parse_ATLexpression(0,s+3,e,entities,types); + if (lft != null && rgt != null) + { // var lft = rgt; in ETL. + rgt.typeCheck(types,entities,new Vector(), new Vector()); + CreationStatement cr = new CreationStatement(rgt.getType() + "", lft + ""); + AssignStatement res = new AssignStatement(lft,rgt); + res.setOperator("="); + SequenceStatement ss = new SequenceStatement(); + ss.addStatement(cr); ss.addStatement(res); + return ss; + } // actually needs to declare lft. + } + else if ("delete".equals(lexicals.get(s) + "")) // for ETL + { Expression dexp = parse_ATLexpression(0,s+1,e,entities,types); + if (dexp != null) + { dexp.setBrackets(true); + Expression del = new UnaryExpression("->isDeleted", dexp); + return new ImplicitInvocationStatement(del); + } + } + else + { for (int i = s; i < e; i++) + { String ss = lexicals.get(i) + ""; + + // System.out.println("Trying to parse assignment " + ss); + + if (i+1 < e && "<".equals(ss) && "-".equals(lexicals.get(i+1) + "") ) + { Expression e1 = parse_ATLbasic_expression(0,s,i-1,entities,types); + Expression e2 = parse_ATLexpression(0,i+2,e,entities,types); + if (e1 == null || e2 == null) + { return null; } + System.out.println("Parsed ATL assignment: " + e1 + " <- " + e2); + AssignStatement res = new AssignStatement(e1,e2); + res.setOperator("<-"); + return res; + } + else if (i+1 < e && ":".equals(ss) && ":=".equals(lexicals.get(i+1) + "") ) + { Expression e1 = parse_ATLbasic_expression(0,s,i-1,entities,types); + Expression e2 = parse_ATLexpression(0,i+2,e,entities,types); + if (e1 == null || e2 == null) + { return null; } + System.out.println("Parsed ETL assignment: " + e1 + " ::= " + e2); + BasicExpression equiv = new BasicExpression("equivalent"); + equiv.objectRef = e2; + equiv.setIsEvent(); + equiv.setParameters(new Vector()); + + AssignStatement res = new AssignStatement(e1,equiv); + res.setOperator("="); + return res; + } + else if ("=".equals(ss)) + { Expression e1 = parse_ATLbasic_expression(0,s,i-1,entities,types); + Expression e2 = parse_ATLexpression(0,i+1,e,entities,types); + if (e1 == null || e2 == null) + { return null; } + System.out.println("Parsed assignment: " + e1 + " = " + e2); + AssignStatement rr = new AssignStatement(e1,e2); + rr.setOperator("="); + return rr; + } + } // = or ::= in ETL. + } + Expression exp = parse_ATLexpression(0,s,e,entities,types); + if (exp != null) + { return new ImplicitInvocationStatement(exp); } + return null; + } + + public Statement parseATLStatement() + { Vector v1 = new Vector(); + Vector v2 = new Vector(); + return parseATLStatement(v1,v2); } + + public Statement parseATLStatement(Vector entities, Vector types) + { return parseATLStatement(0,lexicals.size()-1,entities,types); } + + + public ATLModule parseATL(Vector entities, Vector types) + { if ("module".equals(lexicals.get(0) + "") && + ";".equals(lexicals.get(2) + "")) + { ATLModule mod = new ATLModule(lexicals.get(1) + ""); + for (int i = 0; i < lexicals.size(); i++) + { if ("lazy".equals(lexicals.get(i) + "") || "helper".equals(lexicals.get(i) + "") || + "unique".equals(lexicals.get(i) + "") || "rule".equals(lexicals.get(i) + "")) + { Vector v = parse_ATL_module(i,lexicals.size()-1,entities,types,mod); + mod.setElements(v); + return mod; + } + } + } + return null; + } + + public Vector parse_ATL_module(int st, int en, Vector entities, Vector types, ATLModule mod) + { Vector res = new Vector(); + if (st >= en) + { return res; } + for (int i = st + 2; i <= en; i++) + { if ("lazy".equals(lexicals.get(i) + "") || "rule".equals(lexicals.get(i) + "") || + "unique".equals(lexicals.get(i) + "") || "helper".equals(lexicals.get(i) + "")) + { Rule r = parseATLrule(st,i-1,entities,types,mod); + res = parse_ATL_module(i,en,entities,types,mod); + if (r != null) { res.add(0,r); } + return res; + } + } + Rule r1 = parseATLrule(st,en,entities,types,mod); + if (r1 != null) { res.add(r1); } + return res; + } + + public MatchedRule parseATLrule(int st, int en, Vector entities, Vector types, ATLModule mod) + { boolean lazy = false; + boolean unique = false; + String rname = ""; + int start = st; + + if ("lazy".equals(lexicals.get(st) + "") && + "rule".equals(lexicals.get(st + 1) + "") && + en - st >= 4 && "}".equals(lexicals.get(en) + "")) + { lazy = true; + start = st + 4; + rname = lexicals.get(st + 2) + ""; + } + else if ("unique".equals(lexicals.get(st) + "") && + "lazy".equals(lexicals.get(st + 1) + "") && + en - st >= 5 && "}".equals(lexicals.get(en) + "")) + { lazy = true; + unique = true; + start = st + 5; + rname = lexicals.get(st + 3) + ""; + } + else if ("rule".equals(lexicals.get(st) + "") && + en - st >= 4 && "}".equals(lexicals.get(en) + "")) + { lazy = false; + start = st + 3; + rname = lexicals.get(st + 1) + ""; + } + else if ("helper".equals(lexicals.get(st) + "") && + en - st >= 9 && "context".equals(lexicals.get(st + 1) + "") && + ";".equals(lexicals.get(en) + "")) + { String ent = lexicals.get(st + 2) + ""; + String attname = lexicals.get(st + 5) + ""; + if ("(".equals(lexicals.get(st + 6) + "")) + { // helper operation of an entity or built-in type + for (int p = st+7; p < en; p++) + { String ps = lexicals.get(p) + ""; + if (ps.equals("=")) + { for (int q = p-1; q > st+7; q--) + { String qs = lexicals.get(q) + ""; + if (qs.equals(":")) + { Vector params = parseAttributeDecs(st+7,q-2,entities,types); + Type atType = parseType(q+1,p-1,entities,types); + Expression defn = parse_ATLexpression(0,p+1,en-1,entities,types); + BehaviouralFeature bf = new BehaviouralFeature(attname,params,true,atType); + + Expression resexp = new BasicExpression("result"); + resexp.setType(atType); + resexp.setUmlKind(Expression.VARIABLE); + defn.setBrackets(true); + Expression post = new BinaryExpression("=", resexp, defn); + + bf.setPost(post); // actually to return the defn value + Entity entet = (Entity) ModelElement.lookupByName(ent,entities); + bf.setOwner(entet); + if (entet != null) + { entet.addOperation(bf); } + + mod.addOperation(bf); + return null; + } + } + } + } + } + + // helper 'attribute' - actually a cached operation + for (int r = st+7; r < en; r++) + { String rs = lexicals.get(r) + ""; + if (rs.equals("=")) + { Type restype = parseType(st+7,r-1,entities,types); + // String atttype = lexicals.get(st + 7) + ""; + Expression exp = parse_ATLexpression(0,r+1,en-1,entities,types); + // Attribute att = new Attribute(attname,new Type(atttype,null),ModelElement.INTERNAL); + // att.setInitialExpression(exp); + // Entity ente = (Entity) ModelElement.lookupByName(ent,entities); + // att.setEntity(ente); + // mod.addAttribute(att); + BehaviouralFeature bf = new BehaviouralFeature(attname,new Vector(),true,restype); + Expression resexp = new BasicExpression("result"); + resexp.setType(restype); + resexp.setUmlKind(Expression.VARIABLE); + exp.setBrackets(true); + Expression post = new BinaryExpression("=", resexp, exp); + bf.setPost(post); // actually to return the defn value + Entity ente = (Entity) ModelElement.lookupByName(ent,entities); + bf.setOwner(ente); + if (ente != null) + { ente.addOperation(bf); } + mod.addOperation(bf); + bf.setCached(true); + return null; + } + } + return null; + } + else if ("helper".equals(lexicals.get(st) + "") && + en - st >= 7 && "def".equals(lexicals.get(st + 1) + "") && + ";".equals(lexicals.get(en) + "")) + { String attname = lexicals.get(st + 3) + ""; + if ("(".equals(lexicals.get(st + 4) + "")) + { // helper operation of the ATL module + for (int pp = st+4; pp < en; pp++) + { String pps = lexicals.get(pp) + ""; + if (pps.equals("=")) + { for (int qq = pp-1; qq > st+7; qq--) + { String qqs = lexicals.get(qq) + ""; + if (qqs.equals(":")) + { Vector params = parseAttributeDecs(st+4,qq-2,entities,types); + Type atType = parseType(qq+1,pp-1,entities,types); + Expression defn = parse_ATLexpression(0,pp+1,en-1,entities,types); + BehaviouralFeature bf = new BehaviouralFeature(attname,params,true,atType); + Expression resexp = new BasicExpression("result"); + resexp.setType(atType); + resexp.setUmlKind(Expression.VARIABLE); + defn.setBrackets(true); + Expression post = new BinaryExpression("=", resexp, defn); + + bf.setPost(post); // actually to return the defn value + mod.addOperation(bf); + return null; + } + } + } + } + } + + // static attribute of the module + for (int rr = st+5; rr < en; rr++) + { String rrs = lexicals.get(rr) + ""; + if (rrs.equals("=")) + { Type hrestype = parseType(st+5,rr-1,entities,types); + Expression hexp = parse_ATLexpression(0,rr+1,en-1,entities,types); + Attribute att = new Attribute(attname,hrestype,ModelElement.INTERNAL); + att.setInitialExpression(hexp); + mod.addAttribute(att); + // att.setOwner(mod); + att.setStatic(true); + return null; + } + } + return null; + } + else + { return null; } + + System.out.println("Parsing rule " + rname); + + if ("(".equals(lexicals.get(st+2) + "")) + { for (int d = st + 2; d < en; d++) + { String sd = lexicals.get(d) + ""; + if (sd.equals("{")) + { Vector params = parseAttributeDecs(st+3,d-2,entities,types); + for (int f = d+1; f < en; f++) + { String sf = lexicals.get(f) + ""; + if ("using".equals(sf)) + { for (int g = f+1; g < en; g++) + { String sg = lexicals.get(g) + ""; + if ("to".equals(sg)) + { for (int h = g+1; h < en; h++) + { String hs = lexicals.get(h) + ""; + if ("do".equals(hs)) + { Vector uvars = parseUsingClause(f, g-1, entities, types); + OutPattern toClaus = parseToClause(g, h-1, entities, types); + Statement stat = parseATLStatement(h+2, en-2,entities,types); + MatchedRule cr = new MatchedRule(false,false); + cr.setOutPattern(toClaus); + cr.setUsing(uvars); + cr.setActionBlock(stat); + cr.setName(rname); + cr.setParameters(params); + cr.isCalled = true; + return cr; + } + } + } + else if ("do".equals(sg)) + { Vector uvars = parseUsingClause(f, g-1, entities, types); + Statement stat = parseATLStatement(g+2, en-2, entities,types); + MatchedRule cr = new MatchedRule(false,false); + cr.setUsing(uvars); + cr.setActionBlock(stat); + cr.setName(rname); + cr.setParameters(params); + cr.isCalled = true; + return cr; + } + + } + } + else if ("do".equals(sf)) + { OutPattern toClaus = parseToClause(d+1, f-1, entities, types); + Statement stat = parseATLStatement(f+2, en-2,entities,types); + MatchedRule cr = new MatchedRule(false,false); + cr.setOutPattern(toClaus); + cr.setActionBlock(stat); + cr.setName(rname); + cr.setParameters(params); + cr.isCalled = true; + return cr; + } + } + } + } + } + + + for (int i = start; i < en; i++) + { if ("to".equals(lexicals.get(i) + "")) + { InPattern fromClause = parseFromClause(start, i - 1, entities, types); + for (int j = i; j < en; j++) + { if ("do".equals(lexicals.get(j) + "") && "{".equals(lexicals.get(j+1) + "") && + "}".equals(lexicals.get(en-1) + "") ) + { OutPattern toClause = parseToClause(i, j - 1, entities, types); + Statement stat = parseATLStatement(j+2, en-2,entities,types); + MatchedRule mr = new MatchedRule(lazy, unique); + mr.setInPattern(fromClause); + mr.setOutPattern(toClause); + System.out.println("Action block: " + stat); + mr.setActionBlock(stat); + mr.setName(rname); + return mr; + } + } + OutPattern toClause = parseToClause(i, en - 1, entities, types); + MatchedRule mr = new MatchedRule(lazy, unique); + mr.setInPattern(fromClause); + mr.setOutPattern(toClause); + mr.setName(rname); + return mr; + } + } + return null; + } + + public InPattern parseFromClause(int st, int en, Vector entities, Vector types) + { if ("from".equals(lexicals.get(st) + "")) { } + else { return null; } + + int dec_end = en; + for (int i = st+1; i < en; i++) + { if ("(".equals(lexicals.get(i) + "")) + { dec_end = i - 1; + // System.out.println(dec_end); + break; + } + } + + // System.out.println("Parsing from clause"); + + InPattern res = new InPattern(); + InPatternElement ipe = null; + + for (int j = st+1; j+2 <= dec_end; j = j+4) + { String attname = lexicals.get(j) + ""; + String tname = lexicals.get(j+2) + ""; + + // System.out.println("Input variable " + attname); + + Entity ent = + (Entity) ModelElement.lookupByName(tname,entities); + Type t; + if (ent != null) + { t = new Type(ent); } + else + { t = new Type(tname,null); } + Attribute att = new Attribute(attname,t,ModelElement.INTERNAL); + ipe = new InPatternElement(att,null); + res.addElement(ipe); + } + + if (dec_end < en && ipe != null) + { Expression cond = parse_ATLexpression(1, dec_end + 2, en - 1,entities,types); + ipe.setCondition(cond); + } + + return res; + } + + public OutPattern parseToClause(int st, int en, Vector entities, Vector types) + { if ("to".equals(lexicals.get(st) + "")) { } + else { return null; } + + int dec_end = en; + for (int i = st + 1; i < en; i++) + { if ("do".equals(lexicals.get(i) + "")) + { dec_end = i - 1; + // System.out.println(dec_end); + break; + } + } + + System.out.println("Parsing to clause"); + + OutPattern res = new OutPattern(); + Vector patts = parse_to_clause(st + 1, dec_end, entities, types); + res.setElements(patts); + return res; + } + + + public Vector parse_to_clause(int st, int en, Vector entities, Vector types) + { Vector res = new Vector(); + if (st >= en) { return res; } + + if (":".equals(lexicals.get(st + 1) + "") && + "(".equals(lexicals.get(st + 3) + "") ) + { String att = lexicals.get(st) + ""; + String typ = lexicals.get(st + 2) + ""; + Entity ent = + (Entity) ModelElement.lookupByName(typ,entities); + Type tt; + if (ent != null) + { tt = new Type(ent); } + else + { tt = new Type(typ,null); } + + for (int i = st + 4; i <= en; i++) + { if (")".equals(lexicals.get(i) + "") && + (i == en || + ",".equals(lexicals.get(i + 1) + "") && + ":".equals(lexicals.get(i + 3) + "") + ) ) + { Vector outpat = parse_out_pattern(st + 4, i - 1, entities, types); + Attribute var = new Attribute(att,tt,ModelElement.INTERNAL); + OutPatternElement ope = new OutPatternElement(var); + ope.setBindings(outpat); + if (i < en) + { res = parse_to_clause(i + 2, en, entities, types); } + res.add(0,ope); + return res; + } + } + } + return res; + } + + public Vector parse_out_pattern(int st, int en, Vector entities, Vector types) + // The interior of the ( outpattern ) + { if (st >= en) { return new Vector(); } + Vector res = new Vector(); + + if ("<".equals(lexicals.get(st + 1) + "") && "-".equals(lexicals.get(st + 2) + "")) + { String att = lexicals.get(st) + ""; + for (int i = st + 3; i <= en; i++) + { if (",".equals(lexicals.get(i) + "") && "<".equals(lexicals.get(i + 2) + "") && + "-".equals(lexicals.get(i+3) + "")) + { Expression cond = parse_ATLexpression(1, st + 3, i - 1, entities, types); + if (cond != null) + { Binding b = new Binding(att,cond); + res.add(b); + res.addAll(parse_out_pattern(i + 1, en, entities, types)); + return res; + } + } + } + + Expression cond1 = parse_ATLexpression(1, st + 3, en, entities, types); + // The last binding expression + + if (cond1 != null) + { Binding b1 = new Binding(att,cond1); + res.add(b1); + } + } + + return res; + } + +// using { var : typ = val; ... } +private Vector parseUsingClause(int st, int en, Vector entities, Vector types) +{ if ("using".equals(lexicals.get(st) + "")) {} + else { return null; } + + int st0 = st; + Vector res = new Vector(); + for (int k = st + 2; k < en; k++) + { String lx = lexicals.get(k) + ""; + if (lx.equals(":")) + { String var = lexicals.get(k-1) + ""; + for (int m = k+1; m < en; m++) + { String mx = lexicals.get(m) + ""; + if (mx.equals("=")) + { Type typ = parseType(k+1,m-1,entities,types); + if (typ == null) + { System.err.println("Invalid type: " + showLexicals(k+1,m-1)); + continue; + } + Attribute uvar = new Attribute(var,typ,ModelElement.INTERNAL); + for (int n = m+1; n < en; n++) + { String nx = lexicals.get(n) + ""; + if (nx.equals(";")) + { Expression vdef = parse_ATLexpression(0,m+1,n-1,entities,types); + if (vdef != null) + { uvar.setInitialExpression(vdef); + res.add(uvar); + k = n+1; + } + } + } + } + } + } + } + return res; + } + + + public EtlModule parseEtlModule() + { return parseEtl(new Vector(), new Vector()); } + + public EtlModule parseEtl(Vector entities, Vector types) + { if ("module".equals(lexicals.get(0) + "") && + ";".equals(lexicals.get(2) + "")) + { EtlModule mod = new EtlModule(lexicals.get(1) + ""); + for (int i = 3; i < lexicals.size(); i++) + { String lx = lexicals.get(i) + ""; + if ("pre".equals(lx) || "rule".equals(lx) || "@lazy".equals(lx) || "operation".equals(lx) + || "post".equals(lx)) + { parse_Etl_module(i,lexicals.size()-1,entities,types,mod); + return mod; + } + } + } + return null; + } + + public void parse_Etl_module(int st, int en, Vector entities, Vector types, EtlModule mod) + { if (st >= en) + { return; } + for (int i = st + 2; i <= en; i++) + { String lx = lexicals.get(i) + ""; + if ("pre".equals(lx) || "rule".equals(lx) || "operation".equals(lx) || + "post".equals(lx) || "@lazy".equals(lx)) + { Object r = parseEtlrule(st,i-1,entities,types); + if (r != null) + { parse_Etl_module(i,en,entities,types,mod); + mod.add(r); + return; + } + } + } + Object r1 = parseEtlrule(st,en,entities,types); + if (r1 != null) { mod.add(r1); } + return; + } + + public Object parseEtlrule(int st, int en, Vector entities, Vector types) + { String rname = ""; + int start = st; + + if ("pre".equals(lexicals.get(st) + "") && + "{".equals(lexicals.get(st + 2) + "") && + "}".equals(lexicals.get(en) + "")) + { start = st + 3; + rname = lexicals.get(st + 1) + ""; + Statement stat = parseATLStatement(start,en-1,entities,types); + if (stat != null) + { stat.typeCheck(types,entities,new Vector(),new Vector()); + NamedBlock res = new NamedBlock(rname, stat); + res.setPre(true); + return res; + } + } + else if ("pre".equals(lexicals.get(st) + "") && + "{".equals(lexicals.get(st + 1) + "") && + "}".equals(lexicals.get(en) + "")) + { start = st + 2; + rname = "pre"; + Statement stat = parseATLStatement(start,en-1,entities,types); + if (stat != null) + { stat.typeCheck(types,entities,new Vector(),new Vector()); + NamedBlock res = new NamedBlock(rname, stat); + res.setPre(true); + return res; + } + } + else if ("rule".equals(lexicals.get(st) + "") && + "transform".equals(lexicals.get(st+2) + "") && + "to".equals(lexicals.get(st+6) + "") && + "}".equals(lexicals.get(en) + "") && en - st >= 6) + { start = st + 6; + rname = lexicals.get(st + 1) + ""; + String invar = lexicals.get(st + 3) + ""; + String intype = lexicals.get(st + 5) + ""; + Entity inent = (Entity) ModelElement.lookupByName(intype,entities); + if (inent == null) + { System.err.println("*** Cannot find entity type " + intype); + inent = new Entity(intype); + entities.add(inent); + } + Attribute inatt = new Attribute(invar,new Type(inent),ModelElement.INTERNAL); + inatt.setElementType(new Type(inent)); + // if (whenexp != null) + // { return new FlockRetyping(rname, whenexp, newtype); } + TransformationRule r = new TransformationRule(rname,false,false); + r.setSource(inatt); + + Vector env = new Vector(); + env.add(inatt); + + for (int i = start; i < en; i++) + { if ("{".equals(lexicals.get(i) + "")) + { Vector toclause = parseEtlToClause(start, i-1, entities, types); + r.addTargets(toclause); + Expression g = new BasicExpression(true); + Statement body; + if ("guard".equals(lexicals.get(i+1) + "")) + { for (int j = i+3; j < en - 1; j++) + { g = parse_expression(0,i+3,j); + body = parseATLStatement(j+1,en-1,entities,types); + if (g != null && body != null) + { g.typeCheck(types,entities,new Vector(),env); + + r.setGuard(g); + + env.addAll(toclause); + + body.typeCheck(types,entities,new Vector(),env); + r.setBody(body); + return r; + } + } + } + body = parseATLStatement(i+1,en-1,entities,types); + r.setGuard(g); + + env.addAll(toclause); + + if (body != null) + { body.typeCheck(types,entities,new Vector(),env); } + + r.setBody(body); + return r; + } + } + } + else if ("post".equals(lexicals.get(st) + "") && + "{".equals(lexicals.get(st + 2) + "") && + "}".equals(lexicals.get(en) + "")) + { start = st + 3; + rname = lexicals.get(st + 1) + ""; + Statement stat = parseATLStatement(start,en-1,entities,types); + if (stat != null) + { NamedBlock res = new NamedBlock(rname, stat); + res.setPre(false); + return res; + } + } + else if ("post".equals(lexicals.get(st) + "") && + "{".equals(lexicals.get(st + 1) + "") && + "}".equals(lexicals.get(en) + "")) + { start = st + 2; + rname = "post"; + Statement stat = parseATLStatement(start,en-1,entities,types); + if (stat != null) + { NamedBlock res = new NamedBlock(rname, stat); + res.setPre(false); + return res; + } + } + else if ("@lazy".equals(lexicals.get(st) + "")) + { TransformationRule rr = (TransformationRule) parseEtlrule(st+1,en,entities,types); + rr.setLazy(true); + return rr; + } // same with principal, abstract etc. + else if ("operation".equals(lexicals.get(st) + "")) + { BehaviouralFeature bf = parseEtlOperation(st+1,en,entities,types); + return bf; + } + return null; + } + + public BehaviouralFeature parseEtlOperation(int st, int en, Vector entities, Vector types) + { // operation ContextEntity name(pardecs) { code } + String context = lexicals.get(st) + ""; + String nme = lexicals.get(st+1) + ""; + Entity ent = + (Entity) ModelElement.lookupByName(context,entities); + + for (int i = st+2; i < en; i++) + { String lx = lexicals.get(i) + ""; + if ("{".equals(lx)) + { Vector pars = parseAttributeDecs(st+3,i-2,entities,types); + Statement code = parseATLStatement(i+1, en-1, entities, types); + // deduce the return type from code. + + BehaviouralFeature bf = new BehaviouralFeature(nme, pars, false, null); + bf.setEntity(ent); + bf.setActivity(code); + if (ent != null) { ent.addOperation(bf); } + return bf; + } + } + return null; + } + + + public Vector parseEtlToClause(int st, int en, Vector entities, Vector types) + { if ("to".equals(lexicals.get(st) + "")) { } + else { return null; } + + Vector res = new Vector(); + + for (int j = st+1; j+2 <= en; j = j+4) + { String attname = lexicals.get(j) + ""; + String tname = lexicals.get(j+2) + ""; + + // System.out.println("Output variable " + attname); + + Entity ent = + (Entity) ModelElement.lookupByName(tname,entities); + Type t; + if (ent != null) + { t = new Type(ent); } + else + { System.err.println("*** Cannot find entity type " + tname); + ent = new Entity(tname); + entities.add(ent); + t = new Type(ent); + } + Attribute att = new Attribute(attname,t,ModelElement.INTERNAL); + att.setElementType(t); + res.add(att); + } + + return res; + } // but the to-variables can be of general types, eg: t : Sequence(String) + + + + + public FlockModule parseFlockModule() + { return parseFlock(new Vector(), new Vector()); } + + public FlockModule parseFlock(Vector entities, Vector types) + { if ("module".equals(lexicals.get(0) + "") && + ";".equals(lexicals.get(2) + "")) + { FlockModule mod = new FlockModule(lexicals.get(1) + ""); + for (int i = 3; i < lexicals.size(); i++) + { if ("delete".equals(lexicals.get(i) + "") || "migrate".equals(lexicals.get(i) + "") || + "retype".equals(lexicals.get(i) + "") || "operation".equals(lexicals.get(i) + "")) + { parse_Flock_module(i,lexicals.size()-1,entities,types,mod); + return mod; + } + } + } + return null; + } + + public void parse_Flock_module(int st, int en, Vector entities, Vector types, FlockModule mod) + { if (st >= en) + { return; } + for (int i = st + 2; i <= en; i++) + { if ("delete".equals(lexicals.get(i) + "") || "retype".equals(lexicals.get(i) + "") || + "migrate".equals(lexicals.get(i) + "") || "operation".equals(lexicals.get(i) + "")) + { Object r = parseFlockrule(st,i-1,entities,types); + if (r != null) + { parse_Flock_module(i,en,entities,types,mod); + mod.add(r); + return; + } + } + } + Object r1 = parseFlockrule(st,en,entities,types); + if (r1 != null) { mod.add(r1); } + return; + } + + public Object parseFlockrule(int st, int en, Vector entities, Vector types) + { String rname = ""; + int start = st; + + if ("delete".equals(lexicals.get(st) + "") && + "when".equals(lexicals.get(st + 2) + "") && + ":".equals(lexicals.get(st + 3) + "")) + { start = st + 4; + rname = lexicals.get(st + 1) + ""; + Expression whenexp = parse_expression(0,start,en); + if (whenexp != null) + { return new FlockDeletion(rname, whenexp); } + } + else if ("retype".equals(lexicals.get(st) + "") && + "to".equals(lexicals.get(st+2) + "") && + "when".equals(lexicals.get(st+4) + "") && + ":".equals(lexicals.get(st+5) + "") && en - st >= 6) + { start = st + 6; + rname = lexicals.get(st + 1) + ""; + String newtype = lexicals.get(st + 3) + ""; + Expression whenexp = parse_expression(0,start,en); + if (whenexp != null) + { return new FlockRetyping(rname, whenexp, newtype); } + } + else if ("migrate".equals(lexicals.get(st) + "") && + "when".equals(lexicals.get(st + 2) + "") && + ":".equals(lexicals.get(st + 3) + "") && + "}".equals(lexicals.get(en) + "")) + { start = st + 4; + rname = lexicals.get(st + 1) + ""; + for (int j = start; j < en; j++) + { Vector iglist = new Vector(); + Expression whenexp = new BasicExpression("true"); + if ("ignoring".equals(lexicals.get(j) + "")) + { whenexp = parse_expression(0,start,j-1); + if (whenexp == null) { continue; } + for (int k = j+1; k < en; k++) + { if ("{".equals(lexicals.get(k) + "")) + { j = k; k = en; } + else if (",".equals(lexicals.get(k) + "")) { } + else + { iglist.add(lexicals.get(k) + ""); } + } + } + if ("{".equals(lexicals.get(j) + "")) + { if (iglist.size() == 0) + { whenexp = parse_expression(0,start,j-1); + if (whenexp == null) { continue; } + } + Statement stat = parseStatement(j+1,en-1, entities, types); + MigrateRule res = new MigrateRule(rname, whenexp); + res.setBody(stat); + res.setIgnored(iglist); + return res; + } + } + } + else if ("operation".equals(lexicals.get(st) + "") && + "}".equals(lexicals.get(en) + "")) + { start = st + 1; + String etype = "IN$" + lexicals.get(start); // Owner entity + rname = lexicals.get(st + 2) + ""; // operation name + // skip "(", ")", ":" + String returntype = lexicals.get(st + 6) + ""; // return type + if ("{".equals(lexicals.get(st + 7) + "")) + { Statement stat = parseStatement(st + 8, en - 1, entities, types); + Entity owner = (Entity) ModelElement.lookupByName(etype, entities); + BehaviouralFeature op = new BehaviouralFeature(rname, new Vector(), true, + new Type(returntype,null)); + op.setEntity(owner); + if (owner != null) { owner.addOperation(op); } + op.setActivity(stat); + return op; + } + } + + + return null; + } + + + public MigrateRule parseMigraterule(int st, int en, Vector entities, Vector types) + { String rname = ""; + int start = st; + + if ("migrate".equals(lexicals.get(st) + "") && + "when".equals(lexicals.get(st + 2) + "") && + ":".equals(lexicals.get(st + 3) + "")) + // "}".equals(lexicals.get(en) + "")) + { start = st + 4; + rname = lexicals.get(st + 1) + ""; + for (int j = start; j < en; j++) + { if ("{".equals(lexicals.get(j) + "")) + { Expression whenexp = parse_expression(0,start,j-1); + if (whenexp == null) { continue; } + Statement stat = parseStatement(j+1,en-1,entities,types); + MigrateRule res = new MigrateRule(rname, whenexp); + res.setBody(stat); + return res; + } + } + } + /* else if ("retype".equals(lexicals.get(st) + "") && + "to".equals(lexicals.get(st+2) + "") && + "when".equals(lexicals.get(st+4) + "") && + ":".equals(lexicals.get(st+5) + "") && en - st >= 6) + { start = st + 6; + rname = lexicals.get(st + 1) + ""; + String newtype = lexicals.get(st + 3) + ""; + Expression whenexp = parse_expression(0,start,en); + if (whenexp != null) + { return new FlockRetyping(rname, whenexp, newtype); } + } + else + { return null; } */ + + return null; + } + + public RelationalTransformation parse_QVTR(int st, int en, Vector entities, Vector types) + { String sts = lexicals.get(st) + ""; + String std = lexicals.get(st+2) + ""; + String ens = lexicals.get(en) + ""; + int start = st+3; + String extending = null; + + if ("transformation".equals(sts)) + { for (int i = st + 2; i < en; i++) + { std = lexicals.get(i) + ""; + if ("{".equals(std)) + { start = i+1; + break; + } + else if ("extends".equals(std)) + { extending = lexicals.get(i+1) + ""; } + } + } + else + { System.err.println("!! QVT-R transformation must start with transformation name(parameters)"); + return null; + } + + String nme = lexicals.get(st + 1) + ""; + RelationalTransformation res = new RelationalTransformation(nme); + res.setExtending(extending); + + // int start = st+3; + + for (int w = st + 3; w + 5 < en; w++) + { String wlex = lexicals.get(w) + ""; + if ("key".equals(wlex)) + { // key eId { attname } ; + String eId = lexicals.get(w+1) + ""; + Entity ent = (Entity) ModelElement.lookupByName(eId,entities); + if (ent == null) + { System.err.println(">!! Key declaration error: No entity exists with name: " + eId); + st = w+4; + start = w+6; + break; + } + String attname = lexicals.get(w+3) + ""; + Attribute att = ent.getAttribute(attname); + if (att == null) + { System.err.println(">!! Key declaration error: No entity exists with name: " + eId); + st = w+4; + start = w+6; + break; + } + att.setIdentity(true); + System.out.println(">>> Key constraint for " + eId + "::" + attname); + st = w + 4; + start = w+6; + } + else if ("relation".equals(wlex) || "top".equals(wlex) || "function".equals(wlex)) + { break; } // key declarations come before any relation or query + } + + for (int i = st + 5; i < en; i++) + { String lex = lexicals.get(i) + ""; + if ("relation".equals(lex) || "top".equals(lex) || + "function".equals(lex) || "abstract".equals(lex)) + { Object r = parse_QVT_rule(start,i-1,entities,types,res); + if (r != null && (r instanceof Relation)) + { res.addRule((Relation) r); + start = i; + } + else if (r != null && (r instanceof BehaviouralFeature)) + { res.addFunction((BehaviouralFeature) r); + start = i; + } + else + { System.err.println(">>> Unrecognised QVT element between " + start + " and " + (i-1)); } + } + } + + Object r = parse_QVT_rule(start,en-1,entities,types,res); + if (r != null && (r instanceof Relation)) + { res.addRule((Relation) r); } + else if (r != null && (r instanceof BehaviouralFeature)) + { res.addFunction((BehaviouralFeature) r); } + + return res; + } + + public Object parse_QVT_rule(int st, int en, Vector entities, Vector types, RelationalTransformation trans) + { String sts = lexicals.get(st) + ""; + String ens = lexicals.get(en) + ""; + boolean isAbstract = false; + boolean isTop = true; + Expression wexp = null; + Expression wnexp = null; + Vector variables = new Vector(); + String overrides = null; + + String nme = lexicals.get(st+1) + ""; + int start = st + 3; // after the { + if ("abstract".equals(sts) && "top".equals(lexicals.get(st+1) + "") && + st + 3 < en && "}".equals(ens)) + { isAbstract = true; + isTop = true; + // abstract top relation nme { + nme = lexicals.get(st+3) + ""; + start = st + 5; + } + else if ("abstract".equals(sts) && "relation".equals(lexicals.get(st+1) + "") && + st + 3 < en && "}".equals(ens)) + { isAbstract = true; + isTop = false; + // abstract relation nme { + nme = lexicals.get(st+2) + ""; + start = st + 4; + } + else if ("relation".equals(sts) && st + 3 < en && "}".equals(ens)) + { isTop = false; } + else if ("top".equals(sts) && st + 4 < en && "}".equals(ens)) + { nme = lexicals.get(st + 2) + ""; + // top relation nme { + start = st + 4; + } + else if ("query".equals(sts)) + { return parse_QVT_function(st,en,entities,types); } + else + { return null; } + + for (int x = st + 1; x < en; x++) + { String xlex = lexicals.get(x) + ""; + if ("{".equals(xlex)) + { start = x+1; + String oclause = lexicals.get(x-2) + ""; + if ("overrides".equals(oclause)) + { overrides = lexicals.get(x-1) + ""; } + break; + } + } + + // look for overrides clause. + + int domend = en - 1; + int domstart = start; + + for (int i = start; i < en; i++) + { String istr = lexicals.get(i) + ""; + if ("checkonly".equals(istr) || + "collection".equals(istr) || "enforce".equals(istr) || "primitive".equals(istr)) + { domstart = i; + break; + } + } + + if (domstart > start) // there are some variables + { variables = parseAttributeDecsInit(start,domstart-2,entities,types); } + + for (int i = domstart; i < en; i++) + { String lex = lexicals.get(i) + ""; + if ("when".equals(lex)) + { domend = i-1; + for (int j = i+1; j < en; j++) + { String lx1 = lexicals.get(j) + ""; + if ("where".equals(lx1)) + { wnexp = parse_ATLexpression(0, i+2, j-2, entities, types); + wexp = parse_ATLexpression(0, j+2, en-2, entities, types); + } + } + if (wnexp == null) // where not found + { wnexp = parse_ATLexpression(0, i+2, en-2, entities, types); } + } + } + + if (wnexp == null && wexp == null) // no when clause + { for (int i = start; i < en; i++) + { String lex = lexicals.get(i) + ""; + if ("where".equals(lex)) + { wexp = parse_ATLexpression(0, i+2, en-2, entities, types); + if (wexp != null) + { domend = i-1; } + } + } + } + + Vector domains = parse_domains(domstart, domend, types, entities, trans); + + + if (domains != null) + { Relation res = new Relation(nme, trans); + res.setIsTop(isTop); + res.setIsAbstract(isAbstract); + res.setOverrides(overrides); + res.setDomain(domains); + if (wnexp != null) + { res.addWhen(wnexp); } + if (wexp != null) + { res.addWhere(wexp); } + res.addVariables(variables); + return res; + } + return null; + } + + public Object parse_QVT_function(int st, int en, Vector entities, Vector types) + { String sts = lexicals.get(st) + ""; + String ens = lexicals.get(en) + ""; + String nme = lexicals.get(st+1) + ""; + Type resType = new Type("boolean", null); + Vector pars = new Vector(); + BehaviouralFeature bf = new BehaviouralFeature(nme); + BasicExpression resvar = new BasicExpression("result"); + + for (int i = st+2; i < en; i++) + { String istr = lexicals.get(i) + ""; + if ("{".equals(istr)) // start of function body + { for (int j = i-1; j > st+2; j--) + { String jstr = lexicals.get(j) + ""; + if (":".equals(jstr)) // typing of the function + { resType = parseType(j+1,i-1,entities,types); + if (resType == null) + { System.err.println(">>> Invalid result type for function " + nme); } + + resvar.setType(resType); + bf.setResultType(resType); + + parseOpDecs(st+2, j-1, entities, types, bf); + Expression code = parse_ATLexpression(0,i+1,en-1,entities,types); + if (code == null) + { System.err.println(">>> Invalid expression for function " + nme); } + + BinaryExpression post = new BinaryExpression("=",resvar,code); + bf.setPost(post); + return bf; + } + } + } + } + return null; + } + + + // in general will need to have types such as Set(E) + + private Vector parse_domains(int st, int en, Vector types, Vector entities, RelationalTransformation trans) + { // enforce domain src x : T + String sts = lexicals.get(st) + ""; + String ens = lexicals.get(en) + ""; + boolean checkonly = false; + boolean enforce = false; + boolean primitive = false; + boolean iscollection = false; + Vector res = new Vector(); + + String nme = lexicals.get(st+1) + ""; + int start = st + 2; // start of template or primitive domain + if ("primitive".equals(sts) && ";".equals(ens)) + { nme = lexicals.get(st+2) + ""; + primitive = true; + start = st + 2; + } + else if ("checkonly".equals(sts) && st + 4 < en && ";".equals(ens)) + { checkonly = true; + nme = lexicals.get(st + 2) + ""; + start = st + 3; + if (st + 5 < en && "Set".equals(lexicals.get(st + 4) + "") && + "(".equals(lexicals.get(st+5) + "")) + { iscollection = true; } + else if (st + 5 < en && "Sequence".equals(lexicals.get(st + 4) + "") && + "(".equals(lexicals.get(st+5) + "")) + { iscollection = true; } + } + else if ("enforce".equals(sts) && st + 4 < en && ";".equals(ens)) + { enforce = true; + nme = lexicals.get(st + 2) + ""; + start = st + 3; + } + else if ("collection".equals(sts) && st + 4 < en && ";".equals(ens)) + { iscollection = true; + // checkonly = true; + nme = lexicals.get(st + 2) + ""; + start = st + 3; + } + + TypedModel tm = new TypedModel(nme,trans); + + for (int i = st+2; i <= en; i++) + { String ch = lexicals.get(i) + ""; + if (";".equals(ch)) // end of a domain + { if (primitive) + { Type tt = parseType(st+4,i-1,entities,types); + if (tt == null) + { System.err.println(">>> Invalid type at " + lexicals.get(start)); } + Attribute att = new Attribute(nme,tt,ModelElement.INTERNAL); + att.addStereotype("source"); + PrimitiveDomain pd = new PrimitiveDomain(nme, null, tm, null); + pd.rootVariable = att; + res.add(pd); + } + else if (iscollection) + { TemplateExp cexp = parse_collection_exp(0, start, i-1, entities,types); + if (cexp == null) + { System.err.println(">>> Syntax error in domain " + nme); + continue; + } // should not happen. + + DomainPattern dp = new DomainPattern(null, cexp); + RelationDomain rd = new RelationDomain(nme, null, tm, null, dp); + dp.relationDomain = rd; + rd.setCheckable(true); + rd.setEnforceable(false); + rd.rootVariable = cexp.bindsTo; + // if (checkonly) + { rd.rootVariable.addStereotype("source"); + if (cexp != null) + { cexp.setSource(); } + } + res.add(rd); + } + else + { TemplateExp texp = parse_template_exp(0, start, i-1, entities,types); + if (texp == null) + { System.err.println(">>> Syntax error in domain " + nme); + continue; + } // should not happen. + + DomainPattern dp = new DomainPattern(null, texp); + RelationDomain rd = new RelationDomain(nme, null, tm, null, dp); + dp.relationDomain = rd; + rd.setCheckable(checkonly); + rd.setEnforceable(enforce); + rd.rootVariable = texp.bindsTo; + if (checkonly) + { rd.rootVariable.addStereotype("source"); + if (texp != null) + { texp.setSource(); } + } + res.add(rd); + } + + if (i >= en) { return res; } + sts = lexicals.get(i+1) + ""; + nme = lexicals.get(i+2) + ""; + start = i + 3; // start of template + + System.out.println(">> Next domain: " + sts + " " + nme + " " + + lexicals.get(start)); + + if ("checkonly".equals(sts)) + { checkonly = true; + enforce = false; + primitive = false; + iscollection = false; + nme = lexicals.get(i + 3) + ""; + start = i + 4; + } + else if ("collection".equals(sts)) + { checkonly = true; + enforce = false; + primitive = false; + iscollection = true; + nme = lexicals.get(i + 3) + ""; + start = i + 4; + } + else if ("enforce".equals(sts)) + { enforce = true; + checkonly = false; + primitive = false; + iscollection = false; + nme = lexicals.get(i + 3) + ""; + start = i + 4; + } + else if ("primitive".equals(sts)) + { enforce = false; + checkonly = false; + primitive = true; + iscollection = false; + nme = lexicals.get(i + 3) + ""; + start = i + 5; + } + tm = new TypedModel(nme,trans); + } + } + + return res; + } + + public TemplateExp parse_template_exp(int bc, int st, int en, Vector entities, Vector types) + { // bindsTo : referredClass { f1 = template1, ..., fn = templaten } { optionalExpression } + + if (st > en) { return null; } + + String bind = lexicals.get(st) + ""; + + System.out.println(">>> Parsing domain for " + bind); + + if (st + 4 <= en && (":".equals(lexicals.get(st + 1) + "") || + "<:=".equals(lexicals.get(st + 1) + "") + ) + ) + { String ename = lexicals.get(st + 2) + ""; + Entity e = (Entity) ModelElement.lookupByName(ename,entities); + + if ("{".equals(lexicals.get(st+3) + "") && "}".equals(lexicals.get(st+4) + "")) + { ObjectTemplateExp res = new ObjectTemplateExp(null,null,e); + if ("<:=".equals(lexicals.get(st + 1) + "")) + { res.setLeastChange(true); + // System.out.println(">>> Least-change template: " + res); + } + + res.setpart(new Vector()); + Attribute batt = new Attribute(bind, new Type(e), ModelElement.INTERNAL); + res.bindsTo = batt; + + if (st + 4 < en && "{".equals(lexicals.get(st+5) + "") + && "}".equals(lexicals.get(en) + "")) + { Expression wexp = parse_ATLexpression(bc,st+6,en-1, entities,types); + if (wexp != null) + { res.setConstraint(wexp); } + } + return res; + } + + int expstart = en; + + for (int j = st + 3; j < en; j++) + { String lx1 = lexicals.get(j) + ""; + String lx2 = lexicals.get(j+1) + ""; + if (lx1.equals("}") && lx2.equals("{")) + { expstart = j+2; + Expression wexp = parse_ATLexpression(bc,expstart,en-1,entities,types); + Vector proplist = parse_propertytemplate_list(bc, st + 3, j, e, entities, types); + if (e != null) + { ObjectTemplateExp res = new ObjectTemplateExp(null,null,e); + + if ("<:=".equals(lexicals.get(st + 1) + "")) + { res.setLeastChange(true); + System.out.println(">>> Least-change template: " + res); + } + res.setpart(proplist); + res.setConstraint(wexp); + Attribute batt = new Attribute(bind, new Type(e), ModelElement.INTERNAL); + res.bindsTo = batt; + return res; + } + } + } + + Vector proplist = parse_propertytemplate_list(bc, st + 3, en, e, entities, types); + if (e != null) + { ObjectTemplateExp res = new ObjectTemplateExp(null,null,e); + if ("<:=".equals(lexicals.get(st + 1) + "")) + { res.setLeastChange(true); + // System.out.println(">>> Least-change template: " + res); + } + res.setpart(proplist); + Attribute batt = new Attribute(bind, new Type(e), ModelElement.INTERNAL); + res.bindsTo = batt; + return res; + } + } + return null; + } + + public TemplateExp parse_collection_exp(int bc, int st, int en, Vector entities, Vector types) + { // bindsTo : Set(T) { att1 ++ att2 } { optionalExpression } + + if (st > en) { return null; } + + String bind = lexicals.get(st) + ""; + + if (st + 6 <= en && ":".equals(lexicals.get(st + 1) + "") && + ("Set".equals(lexicals.get(st + 2) + "") || + "Sequence".equals(lexicals.get(st + 2) + "")) + ) + { String ename = lexicals.get(st + 4) + ""; + String ctname = lexicals.get(st + 2) + ""; + + Entity e = (Entity) ModelElement.lookupByName(ename,entities); + + if (e == null) + { System.err.println("!! ERROR: no class called " + ename); + return null; + } + + Type settyp = new Type(ctname, null); + settyp.setElementType(new Type(e)); + + if ("{".equals(lexicals.get(st+6) + "") && + "+".equals(lexicals.get(st+8) + "") && + "+".equals(lexicals.get(st+9) + "") && + "}".equals(lexicals.get(st+11) + "")) + { CollectionTemplateExp res = new CollectionTemplateExp(null,null,settyp); + Attribute batt = new Attribute(bind, settyp, ModelElement.INTERNAL); + batt.setElementType(new Type(e)); + res.bindsTo = batt; + + String member = lexicals.get(st+7) + ""; + Attribute memberatt = new Attribute(member, new Type(e), ModelElement.INTERNAL); + res.setMember(memberatt); + + String rest = lexicals.get(st+10) + ""; + Attribute restatt = new Attribute(rest, settyp, ModelElement.INTERNAL); + restatt.setElementType(new Type(e)); + res.setRest(restatt); + + if (st + 13 < en && "{".equals(lexicals.get(st+12) + "") + && "}".equals(lexicals.get(en) + "")) + { Expression wexp = parse_ATLexpression(bc,st+13,en-1, entities,types); + if (wexp != null) + { res.setConstraint(wexp); } + } + return res; + } + } + return null; + } + + private Vector parse_propertytemplate_list(int bc, int st, int en, Entity scope, Vector entities, Vector types) + { if (scope == null) { return null; } + String sts = lexicals.get(st) + ""; + String ens = lexicals.get(en) + ""; + if ("{".equals(sts) && "}".equals(ens)) { } + else { return null; } + + int cbcnt = 0; + int prev = st + 1; + + Vector res = new Vector(); + for (int i = st+1; i < en; i++) + { String lex = lexicals.get(i) + ""; + if ("{".equals(lex)) { cbcnt++; } + else if ("}".equals(lex)) { cbcnt--; } + else if (",".equals(lex) && "=".equals(lexicals.get(i+2) + "") && cbcnt == 0) + { // prop = value, or prop = template, at top level + + String pname = lexicals.get(prev) + ""; + // System.out.println("Property name = " + pname); + Type typ = scope.getFeatureType(pname); + Attribute att = new Attribute(pname, typ, ModelElement.INTERNAL); + PropertyTemplateItem pti = new PropertyTemplateItem(att); + + if (i == prev + 3) + { Expression val = parse_basic_expression(bc,prev+2,prev+2); + pti.setValue(val); + res.add(pti); + } + else // an object template + { ObjectTemplateExp te = (ObjectTemplateExp) parse_template_exp(bc,prev+2,i-1,entities,types); + if (te != null) + { pti.setTemplate(te); } + else + { Expression ve = parse_expression(bc, prev+2, i-1); + pti.setValue(ve); + } + res.add(pti); + System.out.println(">>> Parsed template item " + pti); + } + prev = i+1; + } + } + String pname = lexicals.get(prev) + ""; + // System.out.println("Property name = " + pname); + + Type typ = scope.getFeatureType(pname); + Attribute att = new Attribute(pname, typ, ModelElement.INTERNAL); + PropertyTemplateItem pti = new PropertyTemplateItem(att); + + if (en == prev + 3) + { Expression val = parse_basic_expression(bc,prev+2,prev+2); + pti.setValue(val); + res.add(pti); + } + else // an object template + { ObjectTemplateExp te = (ObjectTemplateExp) parse_template_exp(bc,prev+2,en-1,entities,types); + if (te != null) + { pti.setTemplate(te); } + else + { Expression ve = parse_expression(bc, prev+2, en-1); + pti.setValue(ve); + } + res.add(pti); + } + // System.out.println("Parsed template item " + pti); + + return res; + } + + + public XMLNode parseXML() + { for (int i = 0; i < lexicals.size(); i++) + { if ("?".equals(lexicals.get(i) + "") && + ">".equals(lexicals.get(i+1) + "")) + { return parsexmlnode(i+2,lexicals.size() - 1); } + } + return null; + } + + public XMLNode parseXMLNode() + { return parsexmlnode(0,lexicals.size() - 1); } + + public XMLNode parsexmlnode(int st, int en) + { if (st < lexicals.size() && "<".equals(lexicals.get(st) + "")) + { String tag = lexicals.get(st + 1) + ""; + + // System.out.println(">>> Parsing XML tag: " + tag); + + XMLNode xnode = new XMLNode(tag); + for (int i = st + 2; i <= en && i < lexicals.size(); i++) + { String str = lexicals.get(i) + ""; + + + if (i + 1 <= en) + { if ("=".equals(lexicals.get(i+1) + "")) + { XMLAttribute xatt = new XMLAttribute(str, lexicals.get(i+2) + ""); + xnode.addAttribute(xatt); + } + else if ("".equals(lexicals.get(i+2) + "")) + { return xnode; } + } + + if (">".equals(str)) + { Vector sns = parsesubnodes(xnode, tag, i+1, en); + xnode.setsubnodes(sns); + return xnode; + } + + if ("/>".equals(str)) + { return xnode; } + } + } + return null; + } + + + public Vector parsesubnodes(XMLNode xnode, String tag, int st, int en) + { Vector res = new Vector(); + // System.out.println(">>> Parsing subnodes of " + tag); + + String content = ""; + + for (int i = st; i <= en; i++) + { String str = lexicals.get(i) + ""; + if ("".equals(lexicals.get(i+2) + "")) + { if (i > st && xnode != null) + { xnode.setContent(content); } + return res; + } + + + if (">".equals(str)) + { String tag1 = lexicals.get(st + 1) + ""; + for (int j = i+1; j < en; j++) + { String str1 = lexicals.get(j) + ""; + if (">> Parsed inner XML node: " + xn); + if (xn != null) { res.add(xn); } + res.addAll(parsesubnodes(null,tag,j+3,en)); + return res; + } + } + } + + if ("".equals(lexicals.get(i+2) + "")) + { XMLNode xn = parsexmlnode(st,i+2); + + // System.out.println(">>> Parsed XML node: " + xn); + + if (xn != null) { res.add(xn); } + res.addAll(parsesubnodes(null,tag,i+3,en)); + return res; + } + + if ("/>".equals(str)) + { XMLNode xn = parsexmlnode(st,i); + + // System.out.println(">>> Parsed XML subnode: " + xn); + + if (xn != null) { res.add(xn); } + res.addAll(parsesubnodes(null,tag,i+1,en)); + return res; + } + else + { content = content + str; } + } + return res; + } + + + public USEMetaModel parseUSEMetaModel() + { USEMetaModel m = null; + int st = 0; + int en = lexicals.size(); + String str = lexicals.get(st) + ""; + if (st < en && "model".equals(str)) + { m = new USEMetaModel(lexicals.get(st + 1) + ""); } + else + { return m; } + return parseUSEdeclarations(m,st + 2,en-1); + } + + public USEMetaModel parseUSEdeclarations(USEMetaModel m, int st, int en) + { if (st > en) { return m; } + + for (int i = st; i <= en; i++) + { String str = lexicals.get(i) + ""; + if ("class".equals(str)) + { for (int j = i; j <= en; j++) + { if ("end".equals(lexicals.get(j) + "")) + { USEClassDeclaration cd = parseUSEClassDeclaration(i,j); + if (cd != null) { m.addClass(cd); } + return parseUSEdeclarations(m,j+1,en); + } + } + } + else if ("association".equals(str)) + { for (int j = i; j <= en; j++) + { if ("end".equals(lexicals.get(j) + "")) + { USEAssociationDeclaration ad = parseUSEAssociationDeclaration(i,j); + if (ad != null) { m.addAssociation(ad); } + return parseUSEdeclarations(m,j+1,en); + } + } + } + } + return m; + } + + public USEClassDeclaration parseUSEClassDeclaration(int st, int en) + { if (st < en) + { String nme = lexicals.get(st + 1) + ""; + return new USEClassDeclaration(nme); + } + return null; + } + + public USEAssociationDeclaration parseUSEAssociationDeclaration(int st, int en) + { if (st + 1 < en) + { String nme = lexicals.get(st + 1) + ""; + USEAssociationDeclaration ad = new USEAssociationDeclaration(nme); + + if ("between".equals(lexicals.get(st + 2) + "")) + { for (int i = st + 3; i + 5 < en; i = i + 6) + { String ent = lexicals.get(i) + ""; + String mult = lexicals.get(i+2) + ""; + String rolename = lexicals.get(i+5) + ""; + System.out.println("Parsed role: " + ent + " " + mult + " " + rolename); + + USERoleDeclaration rle = new USERoleDeclaration(ent,mult,rolename); + ad.addRole(rle); + } + } + return ad; + } + return null; + } + + + + + public static void main(String[] args) + { // System.out.println(Double.MAX_VALUE); + + Compiler2 c0 = new Compiler2(); + // c0.nospacelexicalanalysis("s : Set(E) { x ++ y }"); + // System.out.println(c0.lexicals); + + // c0.nospacelexicalanalysis("m->restrict(Set{1})"); + c0.nospacelexicalanalysis("w/(h*h)"); + int en = c0.lexicals.size(); + Expression e = c0.parseExpression(); + + System.out.println(e); + System.out.println(((BinaryExpression) e).getRight().needsBracket); + + e.typeCheck(new Vector(), new Vector(), new Vector(), new Vector()); + String str = e.queryForm(new java.util.HashMap(), true); + System.out.println(str); + + Compiler2 c1 = new Compiler2(); + c1.nospacelexicalanalysis("m->keys()"); + int ex = c1.lexicals.size(); + Expression eee = c1.parseExpression(); + System.out.println(eee); + eee.typeCheck(new Vector(), new Vector(), new Vector(), new Vector()); + System.out.println(eee.queryFormCSharp(new java.util.HashMap(), true)); + + } + + /* + CGRule r0 = c0.parse_TypeCodegenerationrule("Sequence(_1) |--> ArrayList<_1>"); + + Compiler2 c = new Compiler2(); + Compiler2 c1 = new Compiler2(); + Compiler2 c2 = new Compiler2(); + CGRule r1 = c1.parse_ExpressionCodegenerationrule("_1[_2] |--> (_1).get(_2 - 1) _2 numeric"); + CGRule r2 = c.parse_ExpressionCodegenerationrule("_1._2(_3) |--> _1._2(_3)"); + CGRule r3 = c2.parse_ExpressionCodegenerationrule("_1._2 |--> _1.get_2()"); + // c2.nospacelexicalanalysis("_1->pow(_2)"); + // Expression e3 = c2.parse(); + System.out.println("rule0 = " + r0 + " variables= " + r0.variables); + System.out.println("rule1 = " + r1 + " variables= " + r1.variables); + System.out.println("rule2 = " + r2 + " variables= " + r2.variables); + System.out.println("rule3 = " + r3 + " variables= " + r3.variables); + // System.out.println(e3); + + CGSpec cgs = new CGSpec(); + cgs.addBasicExpressionRule(r1); + cgs.addBasicExpressionRule(r2); + cgs.addBasicExpressionRule(r3); + Compiler2 cc = new Compiler2(); + cc.nospacelexicalanalysis("a.b[3]"); + Expression ff = cc.parse(); + System.out.println(ff.cg(cgs)); */ + + // c.nospacelexicalanalysis("a[i].r.op(5) + a.op1(x).op2(y)"); + // c.nospacelexicalanalysis("package pp { class dd { } class ff { attribute pp : double; } class cc { attribute aa : int ; attribute bb : double; } }"); + // c.displaylexs(); + // Vector rr = c.parseKM3(new Vector(), new Vector(), new Vector(), new Vector()); + // System.out.println(rr); + /* for (int y = 0; y < rr.size(); y++) + { Entity e = (Entity) rr.get(y); + System.out.println(e.getName()); + Vector vv = e.getAttributes(); + for (int i = 0; i < vv.size(); i++) + { System.out.println(vv.get(i)); } + } */ + + // c.nospacelexicalanalysis("s->first"); + // c.nospacelexicalanalysis("(isStatic = true & (isCached = false or parameters.size /= 1) => result = (Statement.tab(indent) + \"def \" + name + \"(\" + Expression.tolist(parameters.name) + \") :\\n\" + activity.toPython(indent + 2) + \"\\n\"))"); + // c.nospacelexicalanalysis("(isStatic = true & isCached = true & parameters.size = 1 => result =(Statement.tab(indent) + \"def \" + name + \"(\" + parameters.first.name + \") :\\n\" + Statement.tab(indent+2) + \"if str(\" + parameters.first.name + \") in \" + owner.name + \".\" + name + \"_cache :\\n\" + Statement.tab(indent + 4) + \"return \" + owner.name + \".\" + name + \"_cache[str(\" + parameters.first.name + \")]\\n\" + Statement.tab(indent+2) + \"result = \" + name + \"_uncached(\" + parameters.first.name + \")\\n\" + Statement.tab(indent+2) + owner.name + \".\" + name + \"_cache[str(\" + parameters.first.name + \")] = result\\n\" + Statement.tab(indent+2) + \"return result\\n\\n\") + (Statement.tab(indent) + \"def \" + name + \"_uncached(\" + Expression.tolist(parameters.name) + \") :\\n\" + activity.toPython(indent + 2) + \"\\n\"))"); + + // c.nospacelexicalanalysis("(Statement.tab(indent) + \"def \" + name + \"(\" + parameters[1].name + \") :\")->display()"); + + // c.nospacelexicalanalysis("(Statement.tab(indent+2) + \"if str(\" + parameters[1].name + \") in \" + owner.name + \".\" + name + \"_cache :\")->display()"); + // c.nospacelexicalanalysis("(Statement.tab(indent + 4) + \"return \" + owner.name + \".\" + name + \"_cache[str(\" + parameters[1].name + \")]\")->display()"); + // c.nospacelexicalanalysis("(Statement.tab(indent+2) + \"result = \" + name + \"_uncached(\" + parameters[1].name + \")\")->display()"); + // c.nospacelexicalanalysis("(Statement.tab(indent+2) + owner.name + \".\" + name + \"_cache[str(\" + parameters[1].name + \")] = result\")->display()"); + // c.nospacelexicalanalysis("(Statement.tab(indent+2) + \"return result\")->display() & (Statement.tab(indent) + \"def \" + name + \"_uncached(\" + Expression.tolist(parameters.name) + \") :\")->display() & activity.toPython(indent + 2)->display()"); + // c.nospacelexicalanalysis("x@pre[att@pre].f@pre"); + // Expression ee = c.parse(); + // System.out.println(ee); + + // c.nospacelexicalanalysis("incr() pre: true post: Ucwithops.att = 10 & \"test\"->display()"); + +// ; d : Sequence ; d := Integer.subrange(0,m)->collect( i | Sequence{} ) ; for i : Integer.subrange(0,m) do ( d[( i + 1 )] := Integer.subrange(0,n)->collect( j | 0 ) ; sq : Sequence ; sq := d->at(i+1) ; sq[0] := i ) ; sq1 : Sequence ; sq1 := d->at(1) ; for j : Integer.subrange(0,n) do sq1[(j+1)] := j ; for j : Integer.subrange(1,n) do for i : Integer.subrange(1,m) do (sqi : Sequence ; sqi := d->at(i+1) ; if s[i] = t[i] then sqi[(j+1)] := (d->at(i))->at(j) else sqi[(j+1)] := Set{ ((d->at(i))->at(j+1)+1), ((d->at(i+1))->at(j)+1), ((d->at(i))->at(j)+1) }->min() ) ; return (d->at(n+1))->at(m+1)"); + + // c.displaylexs(); + // BehaviouralFeature e = c.operationDefinition(new Vector(), new Vector()); + // System.out.println("Parsed: " + e.display()); + // } + + /* + // USEMetaModel xn = c.parseUSEMetaModel(); + // c.nospacelexicalanalysis("module m; create OUT : T from IN : S; rule r { from x : S1, y : S2 ( x.a > 0 ) to p : ET ( d <- 4, h <- x.p ) } rule rr { from x : S2 ( x.b = one ) to k : ET2 ( y <- x.cc ) do { r <- 5; } }"); + // c.nospacelexicalanalysis("for ( v in c.specialization.specific.ownedAttribute ) { if (v.name = a.name) { v->isDeleted() ; } else { skip; } } "); + // c.nospacelexicalanalysis("if ( Entity->includes(att.type) ) { t.tcols->includes( att.makeForeignKeyColumnop() ) ; } else { skip; }"); + // c.nospacelexicalanalysis("result = \"Couple avgRating \" + avgRating + \", \" + commonMovies.size + \" movies (\" + (p1.name.sum + \",\" + p2.name.sum) + \")\""); + /* c.nospacelexicalanalysis("module m; pre pre1 { x := y } rule rr transform x : e1 to y : e2 { guard: x > 0 y := x } post post1 { z := w + 7 }"); + Entity e1 = new Entity("e1"); + Entity e2 = new Entity("e2"); + Vector ents = new Vector(); + ents.add(e1); ents.add(e2); + c.displaylexs(); + EtlModule em = c.parseEtl(ents,new Vector()); + System.out.println(em); + // Statement st = c.parseATLStatement(); + // c.nospacelexicalanalysis("a + b->collect( x | c + x.op() )->max() + d"); + // c.nospacelexicalanalysis("result = Integer.Sum(1, maxfails(k,s), mk, (sectors[k].mu * mk * sectors[k].L * PCond(k,mk) * PS(s - mk * sectors[k].L)))"); + // Expression exp = c.parse(); + // FlockModule m = c.parseFlockModule(); + // System.out.println(exp); + // e1.typeCheck(new Vector(), new Vector(), new Vector()); + // String qf = e1.queryForm(new java.util.HashMap(), true); + // System.out.println(mr); + // System.out.println(mr.getInterpretation()); + // c.nospacelexicalanalysis("It is necessary that each integer type instance t maps to a CPrimitiveType instance c such that c.ctypeId = t.typeId & c.name = \"int\" ; Each Type is considered to be an integer type instance if it has name = \"int\""); + + /* c.nospacelexicalanalysis("nmethods = UMLClass[ci].features->select( f | f : UMLMethod )->size() & natts = UMLClass[ci].features->select( f | f : Attribute )->size() & (nmethods <= 1 => result = 0) & (nmethods > 1 & natts = 0 => result = mmi(ci,ci)/(1.0*nmethods*(nmethods-1))) & (natts /= 0 & nmethods = 1 => result = mai(ci,ci)/(1.0*natts)) & (nmethods > 1 & natts /= 0 => result = (mai(ci,ci)/(1.0*nmethods*natts) + mmi(ci,ci)/(1.0*nmethods*(nmethods-1))))"); + + & + (natts != 0 & nmethods = 1 => + result = mai(ci,ci)/(1.0*natts))"); + + // c.nospacelexicalanalysis("1.0E+100"); + // c.displaylexs(); + // c.nospacelexicalanalysis("execute op() ; while E do execute op1() & op2() & op3()"); + // Statement exp = c.parseStatement(); + + c.nospacelexicalanalysis("(a => b) & (c => d) & (e => f) & (g => h) & (i => j) & (k => l)"); + Expression exp = c.parse(); + System.out.println(Expression.caselist(exp)); + } + + /* c.lexicalanalysis("( kind = initial => n : InitialNode # n.name1 = name ) & ( kind = join => n : JoinNode # n.name1 = name ) & ( kind = fork => n : ForkNode # n.name1 = name ) & ( kind = junction => ( incoming.size = 1 => n : DecisionNode # n.name1 = name ) & ( incoming.size > 1 => n : MergeNode # n.name1 = name ) )"); + c.lexicalanalysis("( ( source : ObjectFlowState or target : ObjectFlowState ) => ( f : ObjectFlow ) # ( f.name1 = name & f.source = ActivityNode[source.name] & f.target = ActivityNode[target.name] & f.guard = OpaqueExpression[guard.name] ) ) & ( ( source /: ObjectFlowState & target /: ObjectFlowState ) => ( f : ControlFlow ) # ( f.name1 = name & f.source = ActivityNode[source.name] & f.target = ActivityNode[target.name] & f.guard = OpaqueExpression[guard.name] ) )"); + + c.lexicalanalysis("ag : ActivityGraph & ag.name = \"ag\" & is : Pseudostate & is.name = \"is\" & is.kind = initial & fs : FinalState & fs.name = \"fs\" & as1 : ActionState & as1.name = \"Request service\" & as2 : ActionState & as2.name = \"Pay\" & as3 : ActionState & as3.name = \"Collect order\" & as4 : ActionState & as4.name = \"Take order\" & as5 : ActionState & as5.name = \"Deliver order\" & as6 : SimpleState & as6.name = \"Restock\" & as7 : ActionState & as7.name = \"Fill order\" & t : Type & of1 : ObjectFlowState & of1.name = \"Placed Order\" & of1.type = t & of2 : ObjectFlowState & of2.name = \"Entered Order\" & of2.type = t & of3 : ObjectFlowState & of3.name = \"Filled Order\" & of3.type = t & of4 : ObjectFlowState & of4.name = \"Delivered Order\" & of4.type = t & ds1 : Pseudostate & ds1.name = "ds1" & ds1.kind = junction & ds2 : Pseudostate & ds2.name = \"ds2\" & ds2.kind = junction & dc1 : Pseudostate & dc1.name = \"dc1\" & dc1.type = fork & dc2 : Pseudostate & dc2.name = \"dc2\" & dc2.type = join & be1 : BooleanExpression & be1.language = \"text\" & be1.body = \"in stock\" & g1 : Guard & g1.name = \"g1\" & g1.expression = be1 & be2 : BooleanExpression & be2.language = \"text\" & be2.body = \"not in stock\" & g2 : Guard & g2.name = \"g2\" & g2.expression = be2 & t0 : Transition & t0.name = \"t0\" & t0.source = is & t0.target = as1 & t1 : Transition & t1.name = \"t1\" & t1.source = as1 & t1.target = dc1 & t2 : Transition & t2.name = \"t2\" & t2.source = dc1 & t2.target = as2 & t3 : Transition & t3.name = \"t3\" & t3.source = as2 & t3.target = dc2 & t4 : Transition & t4.name = \"t4\" & t4.source = dc1 & t4.target = of1 & t5 : Transition & t5.name = \"t5\" & t5.source = of1 & t5.target = as4 & t6 : Transition & t6.name = \"t6\" & t6.source = as4 & t6.target = of2 & t7 : Transition & t7.name = \"t7\" & t7.source = of2 & t7.target = ds1 & t8 : Transition & t8.name = \"t8\" & t8.source = ds1 & t8.target = ds2 & t8.guard = {g1} & t9 : Transition & t9.name = \"t9\" & t9.source = ds1 & t9.target = as6 & t9.guard = {g2} & tr : Event & t10 : Transition & t10.name = \"t10\" & t10.source = as6 & t10.target = ds2 & t10.trigger = {tr} & t11 : Transition & t11.name = \"t11\" & t11.source = ds2 & t11.target = as7 & t12 : Transition & t12.name = \"t12\" & t12.source = as7 & t12.target = of3 & t13 : Transition & t13.name = \"t13\" & t13.source = of3 & t13.target = dc2 & t14 : Transition & t14.name = \"t14\" & t14.source = dc2 & t14.target = as5 & t15 : Transition & t15.name = \"t15\" & t15.source = as5 & t15.target = of4 & t16 : Transition & t16.name = \"t16\" & t16.source = of4 & t16.target = as3 & t17 : Transition & t17.name = \"t17\" & t17.source = as3 & t17.target = fs & cs : CompositeState & cs.name = \"cs\" & cs.subvertex = {is,fs,as1,as2,as3,as4,as5,as6,as7,of1,of2,of3,of4,ds1,ds2,dc1,dc2} & ag.top = cs & ag.transitions = {t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17} & p1 : Partition & p1.name = \"p1\" & p1.contents = {as1,t1,dc1,t4,t2,as2,t16,as3} & p2 : Partition & p2.name = \"p2\" & p2.contents = {t5,as4,t6,t13,dc2,t14,as5,t15} & p3 : Partition & p3.name = \"p3\" & p3.contents = {t7,ds1,t8,t9,as6,as7,ds2,t10,t11,t12} & ag.partition = {p1,p2,p3}"); + + + Expression ss = c.parse(); + System.out.println(ss); + + c.nospacelexicalanalysis("n*m-1"); + System.out.println(c.parse()); + } */ + +/* public class ForStatement extends Statement +{ Expression test; + Statement body; + + public ForStatement(Expression t, Statement b) + { test = t; body = b; } +} */ + + /* public static void main(String[] args) + { Compiler c = new Compiler(); + // c.lexicalanalysis("( x * y ) + ( ( 3 / 2 ) + 4 )"); + c.lexicalanalysis("( x : B ) # ( x.name = \"felix\" & x.y = 2 )"); + System.out.println(c.parse()); + + c.lexicalanalysis("xx + \"ui \n oop\" + \" \" "); + System.out.println(c.parse()); + } */ +} + diff --git a/ConditionalExpression.java b/ConditionalExpression.java new file mode 100644 index 00000000..e8009f60 --- /dev/null +++ b/ConditionalExpression.java @@ -0,0 +1,768 @@ +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ +/* Package: OCL */ + +import java.util.Vector; + + +public class ConditionalExpression extends Expression +{ Expression test; + Expression ifExp; + Expression elseExp; + + public ConditionalExpression(Expression t, Expression ie, Expression ee) + { test = t; ifExp = ie; elseExp = ee; } + + public void setIf(Expression ife) + { ifExp = ife; } + + public void setElse(Expression elsee) + { elseExp = elsee; } + + public Expression getTest() + { return test; } + + public Expression getIfExp() + { return ifExp; } + + public Expression getElseExp() + { return elseExp; } + + public String queryForm(java.util.Map env, boolean local) + { String tqf = test.queryForm(env, local); + String lqf = ifExp.queryForm(env, local); + String rqf = elseExp.queryForm(env, local); + return "((" + tqf + ") ? (" + lqf + ") : (" + rqf + "))"; + } + + public String queryFormJava6(java.util.Map env, boolean local) + { String tqf = test.queryFormJava6(env, local); + String lqf = ifExp.queryFormJava6(env, local); + String rqf = elseExp.queryFormJava6(env, local); + return "((" + tqf + ") ? (" + lqf + ") : (" + rqf + "))"; + } + + public String queryFormJava7(java.util.Map env, boolean local) + { String tqf = test.queryFormJava7(env, local); + String lqf = ifExp.queryFormJava7(env, local); + String rqf = elseExp.queryFormJava7(env, local); + return "((" + tqf + ") ? (" + lqf + ") : (" + rqf + "))"; + } + + public String queryFormCSharp(java.util.Map env, boolean local) + { String tqf = test.queryFormCSharp(env, local); + String lqf = ifExp.queryFormCSharp(env, local); + String rqf = elseExp.queryFormCSharp(env, local); + return "((" + tqf + ") ? (" + lqf + ") : (" + rqf + "))"; + } + + public String queryFormCPP(java.util.Map env, boolean local) + { String tqf = test.queryFormCPP(env, local); + String lqf = ifExp.queryFormCPP(env, local); + String rqf = elseExp.queryFormCPP(env, local); + return "((" + tqf + ") ? (" + lqf + ") : (" + rqf + "))"; + } + + public String updateForm(java.util.Map env, boolean local) + { String tqf = test.queryForm(env, local); + String lqf = ifExp.updateForm(env, local); + if ("true".equals(test + "")) + { return lqf; } + + String rqf = elseExp.updateForm(env, local); + return " if (" + tqf + ") { " + lqf + " }\n" + + " else { " + rqf + " }"; + } + + public String updateFormJava6(java.util.Map env, boolean local) + { String tqf = test.queryFormJava6(env, local); + String lqf = ifExp.updateFormJava6(env, local); + if ("true".equals(test + "")) + { return lqf; } + String rqf = elseExp.updateFormJava6(env, local); + return " if (" + tqf + ") { " + lqf + " }\n" + + " else { " + rqf + " }"; + } + + public String updateFormJava7(java.util.Map env, boolean local) + { String tqf = test.queryFormJava7(env, local); + String lqf = ifExp.updateFormJava7(env, local); + if ("true".equals(test + "")) + { return lqf; } + String rqf = elseExp.updateFormJava7(env, local); + return " if (" + tqf + ") { " + lqf + " }\n" + + " else { " + rqf + " }"; + } + + public String updateFormCSharp(java.util.Map env, boolean local) + { String tqf = test.queryFormCSharp(env, local); + String lqf = ifExp.updateFormCSharp(env, local); + String rqf = elseExp.updateFormCSharp(env, local); + return " if (" + tqf + ") { " + lqf + " }\n" + + " else { " + rqf + " }"; + } + + public String updateFormCPP(java.util.Map env, boolean local) + { String tqf = test.queryFormCPP(env, local); + String lqf = ifExp.updateFormCPP(env, local); + String rqf = elseExp.updateFormCPP(env, local); + return " if (" + tqf + ") { " + lqf + " }\n" + + " else { " + rqf + " }"; + } + + public Statement generateDesign(java.util.Map env, boolean local) + { Statement ifstat = ifExp.generateDesign(env,local); + Statement elsestat = elseExp.generateDesign(env,local); + return new ConditionalStatement(test, ifstat, elsestat); + } + + public int syntacticComplexity() + { int res = test.syntacticComplexity(); + res = res + ifExp.syntacticComplexity(); + res = res + elseExp.syntacticComplexity(); + return res + 1; + } + +public void findClones(java.util.Map clones, String rule, String op) +{ if (this.syntacticComplexity() < 10) { return; } + String val = this + ""; + Vector used = (Vector) clones.get(val); + if (used == null) + { used = new Vector(); } + if (rule != null) + { used.add(rule); } + else if (op != null) + { used.add(op); } + clones.put(val,used); + test.findClones(clones,rule,op); + ifExp.findClones(clones,rule,op); + elseExp.findClones(clones,rule,op); +} + + public int cyclomaticComplexity() + { // 1 + p branches from test + p1 from if + p2 from else + + int tc = test.cyclomaticComplexity(); + int res = ifExp.cyclomaticComplexity(); + res = res + tc + 1 + elseExp.cyclomaticComplexity(); + return res; + } + + public void changedEntityName(String oldN, String newN) + { test.changedEntityName(oldN,newN); + ifExp.changedEntityName(oldN,newN); + elseExp.changedEntityName(oldN,newN); + } + + public Expression addPreForms(String v) + { Expression t1 = test.addPreForms(v); + Expression l1 = ifExp.addPreForms(v); + Expression r1 = elseExp.addPreForms(v); + Expression res = new ConditionalExpression(t1,l1,r1); + res.needsBracket = needsBracket; + return res; + } + + public Expression removePrestate() + { Expression t1 = test.removePrestate(); + Expression l1 = ifExp.removePrestate(); + Expression r1 = elseExp.removePrestate(); + Expression res = new ConditionalExpression(t1,l1,r1); + res.needsBracket = needsBracket; + res.type = type; + res.elementType = elementType; + return res; + } + + public Vector allPreTerms() + { Vector res = test.allPreTerms(); + Vector lpterms = ifExp.allPreTerms(); + Vector rpterms = elseExp.allPreTerms(); + res = VectorUtil.union(res,lpterms); + return VectorUtil.union(res,rpterms); + } + + public Vector allPreTerms(String v) + { Vector res = test.allPreTerms(v); + Vector lpterms = ifExp.allPreTerms(v); + Vector rpterms = elseExp.allPreTerms(v); + res = VectorUtil.union(res,lpterms); + return VectorUtil.union(res,rpterms); + } + + public Vector innermostEntities() + { Vector res = test.innermostEntities(); + Vector r1 = ifExp.innermostEntities(); + res = VectorUtil.union(res,r1); + return VectorUtil.union(res,elseExp.innermostEntities()); + } + + public Vector innermostVariables() + { Vector res = test.innermostVariables(); + Vector r1 = ifExp.innermostVariables(); + res = VectorUtil.union(res,r1); + return VectorUtil.union(res,elseExp.innermostVariables()); + } + + public Vector allEntitiesUsedIn() + { Vector res = test.allEntitiesUsedIn(); + Vector r1 = ifExp.allEntitiesUsedIn(); + res = VectorUtil.union(res,r1); + return VectorUtil.union(res,elseExp.allEntitiesUsedIn()); + } + + public Vector allAttributesUsedIn() + { Vector res = test.allAttributesUsedIn(); + Vector r1 = ifExp.allAttributesUsedIn(); + res = VectorUtil.union(res,r1); + return VectorUtil.union(res,elseExp.allAttributesUsedIn()); + } + + public Expression featureSetting(String var, String feat, Vector remainder) + { // Treat as (test => ifExp) & (not(test) => elseExp) + return null; + } + + public Expression featureSetting2(String var, String feat, Vector remainder) + { // can't return anything because two cases + return null; + } + + public Vector computeNegation4ante(final Vector sms) + { // not(if E then E1 else E2 endif) is + // E & not(E1), not(E) & not(E2) + + Vector res = new Vector(); + res.add(new BinaryExpression("&",test,new UnaryExpression("not", ifExp))); + res.add(new BinaryExpression("&",new UnaryExpression("not", test), + new UnaryExpression("not", elseExp))); + return res; + } + + public Expression computeNegation4succ(final Vector sms) + { return new ConditionalExpression(test, new UnaryExpression("not", ifExp), + new UnaryExpression("not", elseExp)); + } + + public boolean conflictsWith(Expression e) + { if (ifExp.conflictsWith(e) && elseExp.conflictsWith(e)) + { return true; } + return false; + } // and other cases + + public boolean subformulaOf(final Expression e) + { if (e instanceof BinaryExpression) + { BinaryExpression be = (BinaryExpression) e; + if (be.operator.equals("&")) + { return (subformulaOf(be.left) || subformulaOf(be.right)); } + else if (be.operator.equals("#") || be.operator.equals("->exists") || + be.operator.equals("#1") || be.operator.equals("->exists1") || + be.operator.equals("->forAll") || be.operator.equals("!")) + { return subformulaOf(be.right); } // and if be.operator.equals("=>") ??? + else { return false; } + } + else + { return false; } + } + + public boolean selfConsistent(final Vector vars) + { boolean c1 = ifExp.selfConsistent(vars); + boolean c2 = elseExp.selfConsistent(vars); + if (c1 && c2) { return true; } + return false; + } + + public boolean consistentWith(Expression e) + { if (equals(e)) { return true; } + return (ifExp.consistentWith(e) || + elseExp.consistentWith(e)); + } + + public boolean implies(final Expression e) + { if (equals(e)) { return true; } + if (e.equalsString("true")) { return true; } + boolean r1 = ifExp.implies(e); + boolean r2 = elseExp.implies(e); + return r1 && r2; + } + + public Expression removeExpression(final Expression e) + { /* Assumes e is of form v = x */ + if (e == null) + { return this; } + if (("" + this).equals("" + e)) + { return null; } + Expression ifr = ifExp.removeExpression(e); + Expression elser = elseExp.removeExpression(e); + return new ConditionalExpression(test,ifr,elser); + } + + public Expression expandMultiples(Vector sms) + { Expression newleft = + ifExp.expandMultiples(sms); + Expression newright = + elseExp.expandMultiples(sms); + return new ConditionalExpression(test,newleft,newright); + } + + public Vector splitOr(final Vector components) + { Vector res = new Vector(); + Vector lefts = ifExp.splitOr(components); + Vector rights = elseExp.splitOr(components); + for (int i = 0; i < lefts.size(); i++) + { Expression e1 = (Expression) lefts.get(i); + Expression e = new BinaryExpression("&",test,e1); + res.add(e); + } + for (int i = 0; i < rights.size(); i++) + { Expression e2 = (Expression) rights.get(i); + Expression e = new BinaryExpression("&",new UnaryExpression("not",test),e2); + res.add(e); + } + return res; + } + + public Vector splitAnd(Vector sms) + { Vector res = new Vector(); + res.add(this); + return res; + } + + public Object clone() + { ConditionalExpression be = new ConditionalExpression(test, + (Expression) ifExp.clone(), + (Expression) elseExp.clone()); + be.type = type; + be.entity = entity; + be.elementType = elementType; + be.multiplicity = multiplicity; + be.umlkind = umlkind; + be.setBrackets(needsBracket); + return be; + } // is this sufficient? + + public Expression filter(final Vector vars) + { Expression e1 = ifExp.filter(vars); + Expression e2 = elseExp.filter(vars); + return new ConditionalExpression(test,e1,e2); + } + + public String cg(CGSpec cgs) + { String etext = this + ""; + Vector args = new Vector(); + + if ("true".equals(test + "")) + { return ifExp.cg(cgs); } + else if ("false".equals(test + "")) + { return elseExp.cg(cgs); } + + args.add(test.cg(cgs)); + args.add(ifExp.cg(cgs)); + args.add(elseExp.cg(cgs)); + CGRule r = cgs.matchedConditionalExpressionRule(this,etext); + if (r != null) + { return r.applyRule(args); } + return etext; + } + + public Vector metavariables() + { Vector res = test.metavariables(); + res = VectorUtil.union(res,ifExp.metavariables()); + res = VectorUtil.union(res,elseExp.metavariables()); + return res; + } + + public Expression simplify() + { Expression lsimp = ifExp.simplify(); + Expression rsimp = elseExp.simplify(); + if ("true".equals("" + test)) { return lsimp; } + if ("false".equals("" + test)) { return rsimp; } + if (("" + lsimp).equals("" + rsimp)) { return lsimp; } + + return new ConditionalExpression(test,lsimp,rsimp); + } + + public Expression simplify(final Vector vars) + { Expression lsimp = ifExp.simplify(vars); + Expression rsimp = elseExp.simplify(vars); + if ("true".equals("" + test)) { return lsimp; } + if ("false".equals("" + test)) { return rsimp; } + if (("" + lsimp).equals("" + rsimp)) { return lsimp; } + + return new ConditionalExpression(test,lsimp,rsimp); + } + + public Maplet findSubexp(final String var) + { return new Maplet(null,this); } + + public Vector componentsUsedIn(final Vector sms) + { Vector res1 = ifExp.componentsUsedIn(sms); + Vector res2 = elseExp.componentsUsedIn(sms); + return VectorUtil.union(res1,res2); + } + + public Vector variablesUsedIn(final Vector vars) + { Vector res = test.variablesUsedIn(vars); + Vector res1 = ifExp.variablesUsedIn(vars); + Vector res2 = elseExp.variablesUsedIn(vars); + Vector resres = VectorUtil.vector_merge(res,res1); + return VectorUtil.vector_merge(resres,res2); + } // and the test? + + public boolean hasVariable(final String s) + { return (test.hasVariable(s) || ifExp.hasVariable(s) || elseExp.hasVariable(s)); } + // and the test + + public Expression substituteEq(final String oldVar, + final Expression newVal) + { Expression newLeft = null; + if (ifExp != null) + { newLeft = ifExp.substituteEq(oldVar,newVal); } + Expression newRight = null; + if (elseExp != null) + { newRight = elseExp.substituteEq(oldVar,newVal); } + Expression newTest = test.substituteEq(oldVar,newVal); + Expression result = new ConditionalExpression(newTest,newLeft,newRight); + if (needsBracket) + { result.setBrackets(true); } + return result; + } + + public Expression substitute(final Expression oldE, + final Expression newE) + { Expression newR = ifExp.substitute(oldE,newE); + Expression newL = elseExp.substitute(oldE,newE); + Expression newT = test.substitute(oldE,newE); + Expression result = new ConditionalExpression(newT,newL,newR); + result.setBrackets(needsBracket); + return result; + } + + public Expression buildJavaForm(final Vector comps) + { return null; } + + public String toJavaImp(Vector components) + { String basicString = "(" + test.toJavaImp(components) + ")?(" + + ifExp.toJavaImp(components) + "):(" + + elseExp.toJavaImp(components) + ")"; + if (needsBracket) + { return "(" + basicString + ")"; } // eg, for or inside & + else + { return basicString; } + } + + public String toImp(final Vector components) + { + return "(" + test.toImp(components) + ")?(" + + ifExp.toImp(components) + "):(" + + elseExp.toImp(components) + ")"; + } + + public Expression toSmv(Vector cnames) + { Expression tsmv = test.toSmv(cnames); + BinaryExpression case1 = new BinaryExpression("->", tsmv, ifExp.toSmv(cnames)); + BinaryExpression case2 = + new BinaryExpression("->", new UnaryExpression("not", tsmv), elseExp.toSmv(cnames)); + case1.setBrackets(true); + case2.setBrackets(true); + return new BinaryExpression("&", case1, case2); + } // but actually written as test ? if : else in SMV + + public String toZ3() + { String tz3 = test.toZ3(); + return "(ite " + tz3 + " " + ifExp.toZ3() + " " + elseExp.toZ3() + ")"; + } + + public String toB() + { String tsmv = test.toB(); + return "((" + tsmv + " => " + ifExp.toB() + ") & (" + + "not(" + tsmv + ") => " + elseExp.toB() + "))"; + } + + public String toJava() + { String basicString = "(" + test.toJava() + ")?(" + + ifExp.toJava() + "):(" + + elseExp.toJava() + ")"; + if (needsBracket) + { return "(" + basicString + ")"; } // eg, for or inside & + else + { return basicString; } + } + + public String toSQL() + { String ts = test.toSQL(); + String ls = ifExp.toSQL(); + String rs = elseExp.toSQL(); + String res = "((" + ts + " AND " + ls + ") OR (NOT(" + ts + ") AND " + rs + "))"; + return res; + } + + public String toString() + { String res = "if " + test + " then " + ifExp + " else " + elseExp + " endif"; + if (needsBracket) + { res = "(" + res + ")"; } + return res; + } + + public BExpression binvariantForm(java.util.Map env, boolean local) + { BExpression tsmv = test.binvariantForm(env,local); + BExpression case1 = new BBinaryExpression("=>", tsmv, ifExp.binvariantForm(env,local)); + BExpression case2 = new BBinaryExpression("=>", new BUnaryExpression("not", tsmv), + elseExp.binvariantForm(env,local)); + case1.setBrackets(true); + case2.setBrackets(true); + return new BBinaryExpression("&", case1, case2); + } + + public BStatement bupdateForm(java.util.Map env, boolean local) + { BExpression tsmv = test.binvariantForm(env,local); + return new BIfStatement(tsmv, ifExp.bupdateForm(env,local), + elseExp.bupdateForm(env,local)); + } + + public BExpression bqueryForm(java.util.Map env) + { BExpression tsmv = test.binvariantForm(env,true); + BExpression case1 = new BBinaryExpression("=>", tsmv, ifExp.binvariantForm(env,true)); + BExpression case2 = new BBinaryExpression("=>", new BUnaryExpression("not", tsmv), + elseExp.binvariantForm(env,true)); + case1.setBrackets(true); + case2.setBrackets(true); + return new BBinaryExpression("&", case1, case2); + } + + public BExpression bqueryForm() + { BExpression tsmv = test.bqueryForm(); + BExpression case1 = new BBinaryExpression("=>", tsmv, ifExp.bqueryForm()); + BExpression case2 = new BBinaryExpression("=>", new BUnaryExpression("not", tsmv), + elseExp.bqueryForm()); + case1.setBrackets(true); + case2.setBrackets(true); + return new BBinaryExpression("&",case1,case2); + } + + public Expression createActionForm(final Vector sms) + { Expression lact = ifExp.createActionForm(sms); + Expression ract = elseExp.createActionForm(sms); + Expression actionForm = + new BinaryExpression("||",lact,ract); + javaForm = + new BinaryExpression(";",lact.javaForm, + ract.javaForm); + actionForm.javaForm = javaForm; + return actionForm; + } // not correct, should be (test => lact) parallel (not(test) => ract) + + public boolean isOrExpression() { return false; } + + public boolean isMultiple() + { return ifExp.isMultiple() && elseExp.isMultiple(); } + + public int minModality() + { int ml = ifExp.minModality(); + int mr = elseExp.minModality(); + if (ml > mr && mr > ModelElement.NONE) + { return mr; } + return ml; // could be NONE + } + + public int maxModality() + { int ml = ifExp.maxModality(); + int mr = elseExp.maxModality(); + if (ml > mr) + { return ml; } + return mr; + } + + public boolean typeCheck(final Vector types, + final Vector entities, + final Vector contexts, final Vector env) + { test.typeCheck(types,entities,contexts,env); + ifExp.typeCheck(types,entities,contexts,env); + elseExp.typeCheck(types,entities,contexts,env); + if ((ifExp.type + "").equals(elseExp.type + "")) + { type = ifExp.type; + elementType = ifExp.elementType; + return true; + } + else + { System.err.println("WARNING: types in if,else of " + this + " are different"); + type = ifExp.type; + elementType = ifExp.elementType; + return false; + } + } // if and else should have same type, or be type-compatible. Overall type is + // closest common supertype. + + public int typeCheck(Vector sms) + { test.typeCheck(sms); + int tt = ifExp.typeCheck(sms); + elseExp.typeCheck(sms); + if ((ifExp.type + "").equals(elseExp.type + "")) + { return tt; } + else + { System.err.println("WARNING: types in if,else of " + this + " are different"); + return ERROR; + } + } // if and else should have same type. + + public boolean isPrimitive() + { return ifExp.isPrimitive() && elseExp.isPrimitive(); } + + public Expression invert() + { BinaryExpression be1 = new BinaryExpression("=>", test, ifExp); + BinaryExpression be2 = new BinaryExpression("=>", new UnaryExpression("not", test), + elseExp); + be1.setBrackets(true); + be2.setBrackets(true); + Expression invbe1 = be1.invert(); + Expression invbe2 = be2.invert(); + return new BinaryExpression("&", invbe1, invbe2); + } + + public Expression dereference(BasicExpression ref) + { ConditionalExpression res = (ConditionalExpression) clone(); + res.test = test.dereference(ref); + res.ifExp = ifExp.dereference(ref); + res.elseExp = elseExp.dereference(ref); + return res; + } + + public Expression replaceReference(BasicExpression ref, Type t) + { ConditionalExpression res = (ConditionalExpression) clone(); + Expression tr = test.replaceReference(ref,t); + Expression lr = ifExp.replaceReference(ref,t); + Expression rr = elseExp.replaceReference(ref,t); + res.test = tr; + res.ifExp = lr; + res.elseExp = rr; + + return res; + } + + public Expression addReference(BasicExpression ref, Type t) + { ConditionalExpression res = (ConditionalExpression) clone(); + Expression tr = test.addReference(ref,t); + Expression lr = ifExp.addReference(ref,t); + Expression rr = elseExp.addReference(ref,t); + res.test = tr; + res.ifExp = lr; + res.elseExp = rr; + + return res; + } + + public DataDependency rhsDataDependency() + { // if p.f = val then val, p --> f + return null; + } + + public DataDependency getDataItems() + { DataDependency res = ifExp.getDataItems(); + res.union(elseExp.getDataItems()); + return res; + } + + // returns true if opf(val) can possibly make expression true + public boolean relevantOccurrence(String op, Entity ent, + String val, + String f) + { return false; } + + public Vector allBinarySubexpressions() + { // returns new Vector() by default. + Vector res = new Vector(); + return res; + } + + public Vector allValuesUsedIn() + { Vector res = test.allValuesUsedIn(); + res = VectorUtil.union(res,ifExp.allValuesUsedIn()); + return VectorUtil.union(res, + elseExp.allValuesUsedIn()); + } + + public Vector allOperationsUsedIn() + { Vector res = test.allOperationsUsedIn(); + res = VectorUtil.union(res,ifExp.allOperationsUsedIn()); + return VectorUtil.union(res, + elseExp.allOperationsUsedIn()); + } + + public Vector equivalentsUsedIn() + { Vector res = test.equivalentsUsedIn(); + res = VectorUtil.union(res,ifExp.equivalentsUsedIn()); + return VectorUtil.union(res, + elseExp.equivalentsUsedIn()); + } + + public Vector allFeaturesUsedIn() + { Vector res = test.allFeaturesUsedIn(); + res = VectorUtil.union(res,ifExp.allFeaturesUsedIn()); + return VectorUtil.union(res, + elseExp.allFeaturesUsedIn()); + } + + public Vector getUses(String feature) + { Vector res = new Vector(); + res.addAll(test.getUses(feature)); + res.addAll(ifExp.getUses(feature)); + res.addAll(elseExp.getUses(feature)); + return res; + } // VectorUtil.union of the uses? + + public Vector getVariableUses() + { Vector res = new Vector(); + res.addAll(test.getVariableUses()); + res.addAll(ifExp.getVariableUses()); + res.addAll(elseExp.getVariableUses()); + return res; + } // VectorUtil.union of the uses? + + public Expression skolemize(Expression sourceVar, java.util.Map env) + { Expression res; + + Expression tt = test.skolemize(sourceVar,env); + Expression nleft = ifExp.skolemize(sourceVar,env); + Expression nrigh = elseExp.skolemize(sourceVar,env); + res = new ConditionalExpression(tt,nleft,nrigh); + res.setBrackets(needsBracket); + return res; + } + + public Expression determinate() + { Expression dand = + new BinaryExpression("&",test.determinate(), ifExp.determinate()); + Expression pand = + new BinaryExpression("&", dand, elseExp.determinate()); + + return pand.simplify(); + } + + public Expression definedness() + { Expression dand = + new BinaryExpression("=>", test, ifExp.definedness()); + Expression pand = + new BinaryExpression("=>", new UnaryExpression("not", test), elseExp.definedness()); + Expression tdef = test.definedness(); + dand.setBrackets(true); + pand.setBrackets(true); + Expression and1 = new BinaryExpression("&", dand.simplify(), pand.simplify()); + Expression and2 = new BinaryExpression("&", tdef, and1); + + return and2.simplify(); + } + + public void setPre() + { test.setPre(); + ifExp.setPre(); + elseExp.setPre(); + } + +} + \ No newline at end of file diff --git a/Constraint.java b/Constraint.java index 33f5b18e..5090a1ea 100644 --- a/Constraint.java +++ b/Constraint.java @@ -676,6 +676,16 @@ public Vector wr(Vector assocs) return res; } + public Vector cwr(Vector assocs) + { Vector res = new Vector(); + Expression succ = succedent(); + { res.addAll(succ.cwr(assocs)); } + return res; + } + + public DataDependency rhsDataDependency() + { return succ.rhsDataDependency(); } + public Vector allPreTerms() { Expression antced = antecedent(); Expression succed = succedent(); @@ -819,6 +829,9 @@ public void setOwner(Entity e) public void setisPre(boolean e) { ownerisPre = e; } + public void setPrestate(boolean e) + { ownerisPre = e; } + public void setOwner(Entity e, boolean isPre) { owner = e; ownerisPre = isPre; @@ -4436,7 +4449,7 @@ else if (!pars.contains(use.data)) uses.put(use.data,newuses); } } - System.out.println("Variable uses are: " + uses); + // System.out.println("Variable uses are: " + uses); variables = rationaliseVariableTypes(vars,uses,params); } @@ -4457,7 +4470,7 @@ public static Vector variableTypeAssign(Vector v1, Vector params) uses.put(use.data,newuses); } } - System.out.println("Variable uses are: " + uses); + // System.out.println("Variable uses are: " + uses); return rationaliseVariableTypes(vars,uses,params); } @@ -4475,7 +4488,7 @@ public static Vector rationaliseVariableTypes(Vector vars, else { t = Type.determineType(vuses); if (t == null) - { System.out.println("Badly typed variable: " + var); + { System.out.println("!! Warning: Badly typed variable: " + var); t = new Type("Object",null); // why? } } @@ -4483,7 +4496,7 @@ public static Vector rationaliseVariableTypes(Vector vars, for (int j = 0; j < vuses.size(); j++) { BasicExpression be = (BasicExpression) vuses.get(j); be.setType(t); - System.out.println("Type of " + be + " determined as: " + t); + // System.out.println("Type of " + be + " determined as: " + t); } Attribute att = new Attribute(var,t,ModelElement.INTERNAL); @@ -5170,7 +5183,10 @@ public Statement mapToDesign0(UseCase usecase) int parcount = 0; int outerparcount = 0; - // System.out.println("Variables: " + actualvars + " QVARS: " + qvars + " LVARS: " + letVars); + /* JOptionPane.showMessageDialog(null,"Variables: " + actualvars + + " QVARS: " + qvars + " LVARS: " + letVars, "", JOptionPane.WARNING_MESSAGE); + */ + Vector allvars = new Vector(); Vector allpreds = new Vector(); Vector qvars1 = new Vector(); @@ -5182,12 +5198,17 @@ public Statement mapToDesign0(UseCase usecase) v0.add(betrue.clone()); Vector splitante = ante.splitToCond0Cond1Pred(v0,pars1,qvars1,lvars1,allvars,allpreds); // System.out.println("Variables: " + actualvars + " " + qvars1 + " " + lvars1 + " " + allvars); - + + /* JOptionPane.showMessageDialog(null,"Variables: " + actualvars + + " QVARS: " + qvars1 + " LVARS: " + lvars1 + "\n " + + allvars + " " + allpreds, "", JOptionPane.WARNING_MESSAGE); + */ + Expression ante1 = (Expression) splitante.get(0); Expression ante2 = (Expression) splitante.get(1); - // System.out.println("Variable quantifiers: " + ante1); - // System.out.println("Assumptions: " + ante2); + System.out.println("Variable quantifiers: " + ante1); + System.out.println("Assumptions: " + ante2); // if (ante2 == null || "true".equals(ante2 + "")) { res = new ImplicitInvocationStatement(sc); } // else @@ -5234,6 +5255,8 @@ public Statement mapToDesign1(UseCase usecase, Vector types, Vector entities, Ve pars.addAll(usecase.getParameters()); Vector pars1 = ModelElement.getNames(pars); + BasicExpression betrue = new BasicExpression(true); + BasicExpression selfexp = new BasicExpression("self"); selfexp.setEntity(owner); selfexp.setType(new Type(owner)); @@ -5306,11 +5329,10 @@ public Statement mapToDesign1(UseCase usecase, Vector types, Vector entities, Ve // bf.setResultType(new Type("void", null)); bf.setElementType(new Type("void", null)); bf.setBx(usecase.isBx()); - + bf.setPre(betrue); Expression ante = antecedent(); bf.setDerived(true); bf.addStereotype("explicit"); - Expression betrue = new BasicExpression(true); BehaviouralFeature bfouter = null; // used for 2nd-ary vars String bfoutercall = ""; @@ -5433,7 +5455,9 @@ else if (letVars.contains(vname)) call.setCallExp(ef); // the parameters don't have types here Statement forloop = q2LoopsPred(allvars,loopindexes,letVars,call); bfouter = - new BehaviouralFeature(opname + "outer", new Vector(), false, null); + new BehaviouralFeature(opname + "outer", new Vector(), false, voidtype); + bfouter.setElementType(new Type("void", null)); + bfouter.setPre(betrue); bfouter.setPost(betrue); bfouter.setActivity(forloop); bfouter.setDerived(true); @@ -5776,8 +5800,8 @@ public Statement q2LoopsPred(Vector allvars, Vector qvars, Vector lvars, Stateme fs.setLoopKind(Statement.FOR); fs.setLoopRange(vbe,range); // setEntity? - System.out.println("??? FOR loop " + vbe + " : " + range + " Entity: " + - vbe.entity + " range element type: " + range.getElementType()); + // System.out.println("??? FOR loop " + vbe + " : " + range + " Entity: " + + // vbe.entity + " range element type: " + range.getElementType()); return fs; } else if (lvars.contains(v)) @@ -5813,7 +5837,7 @@ else if (lvars.contains(v)) } } else if (obj instanceof Expression) - { IfStatement ifstat = new IfStatement((Expression) obj, innerbody); + { ConditionalStatement ifstat = new ConditionalStatement((Expression) obj, innerbody); return ifstat; } @@ -5827,7 +5851,7 @@ public Statement mapToDesign2(UseCase usecase, String optimise, Vector types, Ve public Statement mapToDesign2(UseCase usecase, String optimise, SequenceStatement oldstat, Vector types, Vector entities) { if (owner == null) - { System.err.println("ERROR: null owner for " + this); + { System.err.println("!!! ERROR: null owner for constraint " + this); return null; } this.usecase = usecase; @@ -5860,8 +5884,11 @@ public Statement mapToDesign2(UseCase usecase, String optimise, Expression nac = succedent().computeNegation4succ(); // Negative application condition + Type voidtype = new Type("void", null); BehaviouralFeature bf = - new BehaviouralFeature(opname, new Vector(), false, null); + new BehaviouralFeature(opname, new Vector(), false, voidtype); + bf.setElementType(new Type("void", null)); + bf.setPre(betrue); bf.setPost(succedent()); bf.setDerived(true); bf.addStereotype("explicit"); @@ -6236,9 +6263,10 @@ public Statement mapToDesign3(UseCase usecase, String optimise, Vector innerss, befalse.setType(booltype); Expression sc = succedent(); // omit update ops from test + Type voidtype = new Type("void", null); BehaviouralFeature bf = - new BehaviouralFeature(opname, new Vector(), false, null); - bf.setBx(usecase.isBx()); + new BehaviouralFeature(opname, new Vector(), false, voidtype); + bf.setElementType(new Type("void", null)); bf.setBx(usecase.isBx()); bf.setPost(sc); bf.setDerived(true); bf.addStereotype("explicit"); diff --git a/ConstraintGroup.java b/ConstraintGroup.java index 107ce2b2..f2c15423 100644 --- a/ConstraintGroup.java +++ b/ConstraintGroup.java @@ -200,6 +200,16 @@ public Vector wr(Vector assocs) return written; } + public Vector cwr(Vector assocs) + { Vector written = new Vector(); + + for (int i = 0; i < elements.size(); i++) + { Constraint cst = (Constraint) elements.get(i); + written.addAll(cst.cwr(assocs)); + } + return written; + } + public Vector readFrame() { return rd(); } @@ -233,6 +243,23 @@ public Vector anteReadFrame() return read; } + public DataDependency getDataFlows() + { for (int i = 0; i < elements.size(); i++) + { Constraint cst = (Constraint) elements.get(i); + return cst.getDataFlows(); + } + return null; + } + + public DataDependency rhsDataDependency() + { for (int i = 0; i < elements.size(); i++) + { Constraint cst = (Constraint) elements.get(i); + return cst.rhsDataDependency(); + } + return null; + } + + public int findGroupType(Vector assocs) { Vector written = new Vector(); diff --git a/ConstraintOrGroup.java b/ConstraintOrGroup.java index cde5fd71..3d423829 100644 --- a/ConstraintOrGroup.java +++ b/ConstraintOrGroup.java @@ -84,6 +84,12 @@ public int getId() public abstract Vector wr(Vector assocs); + public abstract Vector cwr(Vector assocs); + + public abstract DataDependency rhsDataDependency(); + + public abstract DataDependency getDataFlows(); + public abstract void changedEntityName(String oldN, String newN); public abstract Vector operationsUsedIn(); diff --git a/Domain.java b/Domain.java index ad121585..539b773c 100644 --- a/Domain.java +++ b/Domain.java @@ -58,12 +58,14 @@ public Vector objectTemplateAttributes() public abstract boolean typeCheck(Vector entities, Vector types, Vector contexts, Vector env); - public abstract Expression toGuardCondition(Vector bound, Expression post); + public abstract Expression toGuardCondition(Vector bound, Expression post, Entity tr); public abstract Expression toSourceExpression(Vector bound); public abstract Expression toTargetExpression(Vector bound); + public abstract Expression toUndoExpression(Vector bound); + public abstract Expression toSourceExpressionOp(Vector bound); public abstract Expression toTargetExpressionOp(Vector bound); diff --git a/DomainPattern.java b/DomainPattern.java index 617ae271..5d814867 100644 --- a/DomainPattern.java +++ b/DomainPattern.java @@ -21,15 +21,20 @@ public DomainPattern(RelationDomain rd, TemplateExp t) } public Object clone() - { TemplateExp te = (TemplateExp) ((ObjectTemplateExp) templateExpression).clone(); + { if (templateExpression instanceof ObjectTemplateExp) + { TemplateExp te = (TemplateExp) ((ObjectTemplateExp) templateExpression).clone(); + return new DomainPattern(relationDomain, te); + } + TemplateExp te = (TemplateExp) ((CollectionTemplateExp) templateExpression).clone(); return new DomainPattern(relationDomain, te); } public String toString() { return "" + templateExpression; } - public Expression toGuardCondition(Vector bound, Expression contextObj, Expression post) - { return templateExpression.toGuardCondition(bound, contextObj, post); } + public Expression toGuardCondition(Vector bound, Expression contextObj, Expression post, + Entity tr) + { return templateExpression.toGuardCondition(bound, contextObj, post, tr); } public Expression toSourceExpression(Vector bound, Expression contextObj) { return templateExpression.toSourceExpression(bound, contextObj); } @@ -37,6 +42,9 @@ public Expression toSourceExpression(Vector bound, Expression contextObj) public Expression toTargetExpression(Vector bound, Expression contextObj, Expression setting) { return templateExpression.toTargetExpression(bound, contextObj, setting); } + public Expression toUndoExpression(Vector bound, Expression contextObj, Expression setting) + { return templateExpression.toUndoExpression(bound, contextObj, setting); } + public Expression toTargetExpressionOp(Vector bound, Expression contextObj, Expression setting) { return templateExpression.toTargetExpressionOp(bound, contextObj, setting); } diff --git a/Entity.java b/Entity.java index cfde057b..8833fae7 100644 --- a/Entity.java +++ b/Entity.java @@ -64,6 +64,74 @@ public Entity flattenedCopy() public Entity realEntity() { return realEntity; } + public String cg(CGSpec cgs) + { String etext = this + ""; + Vector args = new Vector(); + Vector eargs = new Vector(); + + args.add(getName()); + eargs.add(getName()); + + if (superclass != null) + { args.add(superclass.getName()); + eargs.add(superclass.getName()); + } + else if (superclasses != null && superclasses.size() > 0) + { String allinterfaces = ""; + int nsup = superclasses.size(); + for (int i = 0; i < nsup-1; i++) + { allinterfaces = allinterfaces + ((Entity) superclasses.get(i)).getName(); + allinterfaces = allinterfaces + ", "; + } + allinterfaces = allinterfaces + ((Entity) superclasses.get(nsup-1)).getName(); + args.add(allinterfaces); + eargs.add(superclasses.get(0)); + } + + String arg = ""; + Vector alist = new Vector(); + + for (int x = 0; x < attributes.size(); x++) + { Attribute att = (Attribute) attributes.get(x); + alist.add(att); + String attx = att.cg(cgs); + arg = arg + attx; + } + + + for (int y = 0; y < associations.size(); y++) + { Attribute ast = new Attribute((Association) associations.get(y)); + alist.add(ast); + String astx = ast.cgReference(cgs); + arg = arg + astx; + } + + for (int z = 0; z < operations.size(); z++) + { BehaviouralFeature op = (BehaviouralFeature) operations.get(z); + String opx = op.cg(cgs); + alist.add(op); + arg = arg + opx; + } + + args.add(arg); + eargs.add(alist); + + CGRule r = cgs.matchedEntityRule(this,etext); + if (r != null) + { return r.applyRule(args,eargs,cgs); } + + return etext; + } + + public void generateOperationDesigns(Vector types, Vector entities) + { for (int z = 0; z < operations.size(); z++) + { BehaviouralFeature op = (BehaviouralFeature) operations.get(z); + Statement act = op.generateDesign(this,entities,types); + System.out.println(">>> Activity for operation " + op + " is " + act); + op.setActivity(act); + } + } + public Vector getLocalFeatures() { return localFeatures; } @@ -93,6 +161,52 @@ public Vector getLocalBooleanFeatures() return res; } + public Vector getLocalEnumerationFeatures() + { Vector res = new Vector(); + + for (int i = 0; i < attributes.size(); i++) + { Attribute att = (Attribute) attributes.get(i); + Type t = att.getType(); + if (t != null && t.isEnumeration()) + { res.add(att); } + } + + if (res.size() > 0) + { return res; } + + for (int i = 0; i < localFeatures.size(); i++) + { Attribute att = (Attribute) localFeatures.get(i); + Type t = att.getType(); + if (t != null && t.isEnumeration()) + { res.add(att); } + } + + return res; + } + + public Vector getLocalStringFeatures() + { Vector res = new Vector(); + + for (int i = 0; i < attributes.size(); i++) + { Attribute att = (Attribute) attributes.get(i); + Type t = att.getType(); + if (t != null && t.getName().equals("String")) + { res.add(att); } + } + + if (res.size() > 0) + { return res; } + + for (int i = 0; i < localFeatures.size(); i++) + { Attribute att = (Attribute) localFeatures.get(i); + Type t = att.getType(); + if (t != null && t.getName().equals("String")) + { res.add(att); } + } + + return res; + } + public Vector getLocalReferenceFeatures() { Vector res = new Vector(); @@ -181,6 +295,17 @@ public void computeLeafs() allLeafSubclasses.addAll(getActualLeafSubclasses()); } + public static Vector sourceEntities(Vector entities) + { Vector res = new Vector(); + for (int i = 0; i < entities.size(); i++) + { Entity et = (Entity) entities.get(i); + if (et.isSourceEntity()) + { res.add(et); } + } + return res; + } + + public Entity makeFlattenedCopy(boolean allmaps, int n) { // Combine all direct attributes, associations and inherited and // indirect data features. Up to maximum length of chain = n @@ -351,6 +476,7 @@ public void setActivity(Statement s) public void addPrimaryKey(String nme) { Attribute att = new Attribute(nme,new Type("String",null), ModelElement.INTERNAL); + att.setElementType(new Type("String",null)); att.setUnique(true); att.setEntity(this); attributes.add(0,att); @@ -583,6 +709,13 @@ public String getCardinality() public boolean isInterface() { return hasStereotype("interface"); } + public void setInterface(boolean intf) + { if (intf) + { addStereotype("interface"); } + else + { removeStereotype("interface"); } + } + public boolean isAbstract() { return hasStereotype("abstract"); } @@ -1709,6 +1842,9 @@ public Entity getSuperclass() public Vector getSubclasses() { return subclasses; } + public boolean hasInterfaces() + { return superclasses != null && superclasses.size() > 0; } + public Vector getSuperclasses() { Vector res = new Vector(); if (superclass != null) @@ -3119,26 +3255,33 @@ public double nmsSimilarity(Entity e, Vector thesaurus) public static double nmsSimilarity(String fnme, String fenme, Vector thesaurus) { double totalscore = 0; - totalscore = Thesarus.findSimilarity(fnme,fenme,thesaurus); // if (totalscore > 0) // { return totalscore; } Vector w1 = ModelElement.splitIntoWords(fnme); + int n1 = w1.size(); Vector w2 = ModelElement.splitIntoWords(fenme); - - for (int i = 0; i < w1.size(); i++) - { String word1 = (String) w1.get(i); - for (int j = 0; j < w2.size(); j++) - { String word2 = (String) w2.get(j); - double wscore = Thesarus.findSimilarity(word1,word2,thesaurus); - totalscore = (totalscore + wscore) - (totalscore*wscore); + int n2 = w2.size(); + + if (n1 + n2 > 2) + { for (int i = 0; i < w1.size(); i++) + { String word1 = (String) w1.get(i); + for (int j = 0; j < w2.size(); j++) + { String word2 = (String) w2.get(j); + double wscore = Thesarus.findSimilarity(word1,word2,thesaurus); + totalscore = (totalscore + wscore) - (totalscore*wscore); + } } + totalscore = totalscore*(2.0/(n1 + n2)); } + else + { totalscore = Thesarus.findSimilarity(fnme,fenme,thesaurus); } + int res = (int) Math.round(totalscore*1000); return res/1000.0; - } // also break up the names into parts + } // also break up the names into parts based on suffixes, prefixes. public Vector getActualLeafSubclasses() // recursively { Vector res = new Vector(); @@ -4636,6 +4779,9 @@ public Attribute getPrincipalKey() } // a bad error return res; } + + public Attribute getPrincipalPrimaryKey() + { return getPrincipalKey(); } public void generateJava(PrintWriter out) { generateJava(new Vector(), new Vector(),out); } @@ -7309,6 +7455,11 @@ public static boolean isAncestor(Entity a, Entity b) return isAncestor(a,s); } + public static boolean isDescendant(Entity a, Entity b) + { if (a == b) { return true; } + return isAncestor(b,a); + } + public static boolean inheritanceRelated(Entity a, Entity b) { if (a == null) { return false; } @@ -9859,25 +10010,34 @@ public String getValueObject() { return getValueObject("beans"); } - public String getAndroidValueObject() - { return getValueObject("com.example.app"); } + public String getAndroidValueObject(String systemName) + { return getValueObject("com.example." + systemName); } public String getValueObject(String pge) { String res = "package " + pge + ";\n\n"; + res = res + "import java.util.List;\n" + + "import java.util.ArrayList;\n\n"; + String nme = getName(); res = res + "public class " + nme + "VO\n" + "{ \n"; + + String stringout = ""; + for (int i = 0; i < attributes.size(); i++) { Attribute att = (Attribute) attributes.get(i); String attnme = att.getName(); String tname = att.getType().getJava(); if (tname.equals("boolean")) { tname = "String"; } - res = res + " private " + tname + " " + attnme + ";\n"; + res = res + " private " + tname + " " + attnme + ";\n"; + stringout = stringout + "\"" + attnme + "= \" + " + attnme; + if (i < attributes.size() - 1) + { stringout = stringout + " + \",\" + "; } } res = res + "\n" + - " public " + nme + "VO() {}\n" + + " public " + nme + "VO() {}\n\n" + " public " + nme + "VO("; boolean previous = false; @@ -9902,6 +10062,17 @@ public String getValueObject(String pge) res = res + " " + attnme + " = " + attnme + "x;\n"; } res = res + " }\n\n"; + + res = res + " public String toString()\n" + + " { return (" + stringout + "); }\n\n"; + + res = res + " public List toStringList(List<" + nme + "VO> list)\n" + + " { List _res = new ArrayList();\n" + + " for (int i = 0; i < list.size(); i++)\n" + + " { " + nme + "VO _x = (" + nme + "VO) list.get(i);\n" + + " _res.add(_x.toString()); \n" + + " }\n" + + " }\n\n"; for (int i = 0; i < attributes.size(); i++) { Attribute att = (Attribute) attributes.get(i); @@ -9928,39 +10099,83 @@ public String getValueObject(String pge) return res + "}\n\n"; } -public void androidDbi(PrintWriter out) + public String getIOSValueObject(String pge) + { String res = ""; + String nme = getName(); + res = res + "class " + nme + "VO\n" + + "{ \n"; + for (int i = 0; i < attributes.size(); i++) + { Attribute att = (Attribute) attributes.get(i); + String attnme = att.getName(); + String tname = att.getType().getSwift(); + res = res + " " + attnme + " : " + tname + "\n"; + } + res = res + "\n" + + " init() {}\n\n" + + " init("; + boolean previous = false; + + for (int i = 0; i < attributes.size(); i++) + { Attribute att = (Attribute) attributes.get(i); + String tname = att.getType().getSwift(); + + String par = att.getName() + "x" + " : " + tname; + if (previous) + { res = res + "," + par; } + else + { res = res + par; + previous = true; + } + } + res = res + ") {\n"; + for (int i = 0; i < attributes.size(); i++) + { Attribute att = (Attribute) attributes.get(i); + String attnme = att.getName(); + res = res + " " + attnme + " = " + attnme + "x\n"; + } + res = res + " }\n\n"; + + for (int i = 0; i < attributes.size(); i++) + { Attribute att = (Attribute) attributes.get(i); + String attnme = att.getName(); + String tname = att.getType().getSwift(); + + res = res + " func get" + attnme + "() -> " + tname + "\n { " + + "return " + attnme + " }\n\n"; + } + + for (int i = 0; i < attributes.size(); i++) + { Attribute att = (Attribute) attributes.get(i); + String attnme = att.getName(); + String tname = att.getType().getSwift(); + + res = res + " func set" + attnme + "(_x : " + tname + ")\n { " + + attnme + " = _x }\n\n"; + } + + return res + "}\n\n"; + } + +public void androidDbiDeclarations(PrintWriter out) { String ent = getName(); String entlc = ent.toLowerCase(); int natts = attributes.size(); - out.println("package com.example.app;"); - out.println(); - out.println(); - out.println("import android.content.Context;"); - out.println("import android.database.sqlite.SQLiteDatabase;"); - out.println("import android.database.sqlite.SQLiteOpenHelper;"); - out.println("import android.content.ContentValues;"); - out.println("import android.database.Cursor;"); - out.println("import java.util.Vector;"); - out.println(); - out.println("public class Dbi extends SQLiteOpenHelper"); - out.println("{ static final String TABLE_NAME = \"" + ent + "\";"); - out.println(" public static final int COL_ID = 0;"); + + out.println(" static final String " + ent + "_TABLE_NAME = \"" + ent + "\";"); + out.println(" static final int " + ent + "_COL_ID = 0;"); String colnames = "{\"_id\""; for (int x = 0; x < natts; x++) { Attribute att = (Attribute) attributes.get(x); String aname = att.getName(); String auname = aname.toUpperCase(); - out.println(" static final int COL_" + auname + " = " + (x+1) + ";"); + out.println(" static final int " + ent + "_COL_" + auname + " = " + (x+1) + ";"); colnames = colnames + ", \"" + aname + "\""; } - out.println(" static final String[] COLS = new String[]" + colnames + "};"); - out.println(" static final int NUMBER_COLS = " + natts + ";"); - out.println(); - out.println(" SQLiteDatabase database;"); + + out.println(" static final String[] " + ent + "_COLS = new String[]" + colnames + "};"); + out.println(" static final int " + ent + "_NUMBER_COLS = " + natts + ";"); out.println(); - out.println(" private static final String DBNAME = \"app.db\";"); - out.println(" private static final int DBVERSION = 1;"); - out.println(" private static final String CREATE_SCHEMA ="); + out.println(" private static final String " + ent + "_CREATE_SCHEMA ="); out.println(" \"create table " + ent + " (" + "_id integer primary key autoincrement\" + "); for (int x = 0; x < attributes.size(); x++) @@ -9969,26 +10184,32 @@ public void androidDbi(PrintWriter out) String dbtype = att.dbType(); out.println(" \", " + attname + " " + dbtype + " not null\" + "); } - out.println(" )\";"); + out.println(" \" )\";"); + out.println(); +} + +public void androidDbiOperations(PrintWriter out) +{ String ent = getName(); + String entlc = ent.toLowerCase(); + int natts = attributes.size(); + String attlist = ""; + out.println(); - out.println(" public Dbi(Context context)"); - out.println(" { super(context, DBNAME, null, DBVERSION); }"); - out.println(); - out.println(" @Override"); - out.println(" public void onCreate(SQLiteDatabase db)"); - out.println(" { db.execSQL(CREATE_SCHEMA); }"); - out.println(); - out.println(" public Vector list" + ent + "()"); - out.println(" { Vector res = new Vector();"); + out.println(" public ArrayList<" + ent + "VO> list" + ent + "()"); + out.println(" { ArrayList<" + ent + "VO> res = new ArrayList<" + ent + "VO>();"); out.println(" database = getWritableDatabase();"); - out.println(" Cursor cursor = database.query(TABLE_NAME,COLS,null,null,null,null,null);"); + out.println(" Cursor cursor = database.query(" + ent + + "_TABLE_NAME," + ent + "_COLS,null,null,null,null,null);"); out.println(" cursor.moveToFirst();"); out.println(" while(!cursor.isAfterLast())"); out.println(" { " + ent + "VO " + entlc + "vo = new " + ent + "VO();"); for (int y = 0; y < natts; y++) - { Attribute att = (Attribute) attributes.get(y); - String anme = att.getName(); - String getop = att.androidExtractOp(); + { Attribute attx = (Attribute) attributes.get(y); + String anme = attx.getName(); + attlist = attlist + anme; + if (y < natts-1) + { attlist = attlist + ", "; } + String getop = attx.androidExtractOp(ent); out.println(" " + entlc + "vo.set" + anme + "(" + getop + ");"); } out.println(" res.add(" + entlc + "vo);"); @@ -10000,25 +10221,72 @@ public void androidDbi(PrintWriter out) out.println(); out.println(" public void create" + ent + "(" + ent + "VO " + entlc + "vo)"); out.println(" { database = getWritableDatabase();"); - out.println(" ContentValues _wr = new ContentValues(NUMBER_COLS);"); + out.println(" ContentValues _wr = new ContentValues(" + ent + + "_NUMBER_COLS);"); for (int z = 0; z < natts; z++) { Attribute att = (Attribute) attributes.get(z); String nmeatt = att.getName(); String nup = nmeatt.toUpperCase(); - out.println(" _wr.put(COLS[COL_" + nup + "]," + entlc + "vo.get" + nmeatt + "());"); + out.println(" _wr.put(" + ent + "_COLS[" + ent + + "_COL_" + nup + "]," + entlc + "vo.get" + nmeatt + "());"); } - out.println(" database.insert(TABLE_NAME,COLS[1],_wr);"); + out.println(" database.insert(" + ent + "_TABLE_NAME," + ent + "_COLS[1],_wr);"); out.println(" }"); out.println(); - out.println(" public void delete" + ent + "(String " + entlc + "Id)"); + + String entId = entlc + "Id"; + Attribute pk = getPrincipalPrimaryKey(); + if (pk != null) + { entId = pk.getName(); } + + for (int k = 0; k < attributes.size(); k++) + { Attribute att = (Attribute) attributes.get(k); + String attname = att.getName(); + out.println(); + out.println(" public ArrayList<" + ent + "VO> searchBy" + ent + attname + "(String _val)"); + out.println(" { ArrayList<" + ent + "VO> res = new ArrayList<" + ent + "VO>();"); + out.println(" database = getWritableDatabase();"); + out.println(" String[] _args = new String[]{_val};"); + out.println(" Cursor cursor = database.rawQuery(\"select " + attlist + + " from " + ent + " where " + attname + " = ?\", _args);"); + out.println(" cursor.moveToFirst();"); + out.println(" while(!cursor.isAfterLast())"); + out.println(" { " + ent + "VO " + entlc + "vo = new " + ent + "VO();"); + for (int y = 0; y < natts; y++) + { Attribute attx = (Attribute) attributes.get(y); + String anme = attx.getName(); + String getop = attx.androidExtractOp(ent); + out.println(" " + entlc + "vo.set" + anme + "(" + getop + ");"); + } + out.println(" res.add(" + entlc + "vo);"); + out.println(" cursor.moveToNext();"); + out.println(" }"); + out.println(" cursor.close();"); + out.println(" return res;"); + out.println(" }"); + out.println(); + } + + out.println(" public void edit" + ent + "(" + ent + "VO " + entlc + "vo)"); + out.println(" { database = getWritableDatabase();"); + out.println(" ContentValues _wr = new ContentValues(" + ent + "_NUMBER_COLS);"); + for (int z = 0; z < natts; z++) + { Attribute att = (Attribute) attributes.get(z); + String nmeatt = att.getName(); + String nup = nmeatt.toUpperCase(); + out.println(" _wr.put(" + ent + "_COLS[" + ent + "_COL_" + nup + "]," + + entlc + "vo.get" + nmeatt + "());"); + } + out.println(" String[] _args = new String[]{" + entlc + "vo.get" + entId + "() };"); + out.println(" database.update(" + ent + "_TABLE_NAME, _wr, \"" + entId + " =?\", _args);"); + out.println(" }"); + out.println(); + out.println(" public void delete" + ent + "(String _val)"); out.println(" { database = getWritableDatabase();"); - out.println(" String[] _args = new String[]{" + entlc + "Id};"); - out.println(" database.delete(TABLE_NAME, \"" + entlc + "Id = ?\", _args);"); + out.println(" String[] _args = new String[]{ _val };"); + out.println(" database.delete(" + ent + "_TABLE_NAME, \"" + entId + " = ?\", _args);"); out.println(" }"); out.println(); - out.println(" public void onUpgrade(SQLiteDatabase d, int x, int y) {}"); - out.println(); - out.println("}"); } @@ -10097,7 +10365,7 @@ else if (tname.equals("double")) Vector pars = od.getParameters(); String odname = od.getODName(); String action = od.getStereotype(0); - String dbiop = od.getDbiOp(); + String dbiop = od.getDbiOpCall(); Vector correc = new Vector(); if (action.equals("create") || action.equals("delete") || @@ -10159,7 +10427,7 @@ public String generateAndroidBean(Vector useCases, Vector cons, Vector entities, String attnme = att.getName(); String tname = att.getType().getName(); res = res + " private String " + attnme + " = \"\";\n"; - if (tname.equals("int")) + if (tname.equals("int") || tname.equals("long")) { res = res + " private int i" + attnme + " = 0;\n"; } else if (tname.equals("double")) { res = res + " private double d" + attnme + " = 0;\n"; } @@ -10222,7 +10490,7 @@ else if (tname.equals("double")) Vector pars = od.getParameters(); String odname = od.getODName(); String action = od.getStereotype(0); - String dbiop = od.getAndroidDbiOp(); + String dbiop = od.getAndroidDbiOpCall(); Vector correc = new Vector(); if (action.equals("create") || action.equals("delete") || @@ -10258,7 +10526,7 @@ else if (tname.equals("double")) } res = res + " public Iterator " + odname + "()\n" + " { "; - res = res + "Vector rs = " + dbiop + "\n" + + res = res + "List rs = " + dbiop + "\n" + " List rs_list = new ArrayList();\n" + " rs_list.addAll(rs);\n" + " resetData();\n" + diff --git a/EntityMatching.java b/EntityMatching.java index ffb09c4a..b9e2f1e5 100644 --- a/EntityMatching.java +++ b/EntityMatching.java @@ -25,10 +25,14 @@ public class EntityMatching implements SystemTypes String trgname = ""; Vector attributeMappings = new Vector(); // of AttributeMatching Expression condition = null; + Expression postcondition = null; ObjectTemplateExp sourceTemplate; ObjectTemplateExp targetTemplate; + boolean isSecondary = false; // for ATL, another entity mapping is the primary mapping + String isSecondaryTo = ""; // The name of the primary mapping + public EntityMatching(Entity asrc, Entity atrg) { src = asrc; trg = atrg; @@ -41,6 +45,14 @@ public EntityMatching(Entity asrc, Entity atrg) public EntityMatching(Entity source, Entity target, Vector entities) { src = source; trg = target; + if (src == null) + { System.err.println("!!! Null source in entity match to " + target); + return; + } + if (trg == null) + { System.err.println("!!! Null target in entity match from " + source); + return; + } srcname = src.getName(); trgname = trg.getName(); @@ -64,9 +76,50 @@ public EntityMatching(Entity source, Entity target, Vector entities) public void setCondition(Expression e) { condition = e; } + public void setPostcondition(Expression e) + { postcondition = e; } + public void addCondition(Expression e) { condition = Expression.simplify("&",condition,e,null); } + public Expression getCondition() + { return condition; } + + public boolean isPrimary() + { return !isSecondary; } + + public boolean isSecondary() + { return isSecondary; } + + public boolean unconditional() + { if (condition == null) + { return true; } + if ("true".equals(condition + "")) + { return true; } + return false; + } + + public boolean hasAssignmentOf(String value) + { // Some e --> t has e as "value" + for (int i = 0; i < attributeMappings.size(); i++) + { AttributeMatching am = (AttributeMatching) attributeMappings.get(i); + if ((am.src + "").equals("\"" + value + "\"")) + { return true; } + if ((am.srcvalue + "").equals("\"" + value + "\"")) + { return true; } + } + return false; + } + + public boolean inheritanceRelatedTo(EntityMatching otherem) + { // realsrc is ancestor, equal to or descendent of otherem.realsrc + + if (realsrc == otherem.realsrc) { return true; } + else if (Entity.isAncestor(realsrc, otherem.realsrc)) { return true; } + else if (Entity.isAncestor(otherem.realsrc, realsrc)) { return true; } + return false; + } + public EntityMatching reverse() { EntityMatching inv = new EntityMatching(realtrg,realsrc); return inv; @@ -78,27 +131,48 @@ public void invert(Vector ems) { return; } Vector invams = new Vector(); + if (condition != null) + { Vector amconds = AttributeMatching.invertCondition(condition,realsrc,realtrg); + invams.addAll(amconds); + } + + Vector seen = new Vector(); + for (int i = 0; i < attributeMappings.size(); i++) { AttributeMatching am = (AttributeMatching) attributeMappings.get(i); - if (am.isStringAssignment()) + if (am.isPossibleFeatureMerge() && !(seen.contains(am))) + { Vector otherams = am.findMergeFamily(attributeMappings,seen); + if (otherams.size() > 1) + { AttributeMatching aminv = inverseMerge(otherams); + invams.add(aminv); + seen.addAll(otherams); + } + } + + if (am.isStringAssignment() && !(seen.contains(am))) { Vector res = am.inverts(realsrc,realtrg,ems); if (res != null) { invams.addAll(res); } + seen.add(am); } - else if (am.isExpressionAssignment()) + else if (am.isExpressionAssignment() && !(seen.contains(am))) { Vector res = am.inverts(realsrc,realtrg,ems); if (res != null) { invams.addAll(res); } + seen.add(am); } - else if (am.isValueAssignment()) + else if (am.isValueAssignment() && !(seen.contains(am))) { BasicExpression trgfeature = new BasicExpression(am.trg); trgfeature.setUmlKind(Expression.ATTRIBUTE); Expression e = new BinaryExpression("=",trgfeature,am.srcvalue); e.setType(new Type("boolean",null)); inv.addCondition(e); + seen.add(am); } - else - { invams.add(am.invert()); } + else if (!seen.contains(am)) + { invams.add(am.invert()); + seen.add(am); + } } inv.src = trg; inv.trg = src; @@ -108,8 +182,40 @@ else if (am.isValueAssignment()) return; } + public AttributeMatching inverseMerge(Vector ams) + { // x->before(s) --> t1 and x->after(s) --> t2 invert to t1 + s + t2 --> x + + AttributeMatching am1 = (AttributeMatching) ams.get(0); + AttributeMatching am2 = (AttributeMatching) ams.get(1); + + Expression t1 = new BasicExpression(am1.trg); + t1.setUmlKind(Expression.ATTRIBUTE); + Expression t2 = new BasicExpression(am2.trg); + t2.setUmlKind(Expression.ATTRIBUTE); + Expression sep = ((BinaryExpression) am1.srcvalue).getRight(); + BinaryExpression news1 = new BinaryExpression("+", t1, sep); + BinaryExpression news = new BinaryExpression("+", news1, t2); + news.setType(new Type("String",null)); + news.setElementType(new Type("String", null)); + news.setMultiplicity(ModelElement.ONE); + + Expression x = ((BinaryExpression) am1.srcvalue).getLeft(); + AttributeMatching res = new AttributeMatching(news,x); + res.setElementVariable(am1.trg); + res.addAuxVariable(am1.trg); + res.addAuxVariable(am2.trg); + return res; + } // must be a String matching + + + + public void setAttributeMatches(Vector ams) - { attributeMappings.addAll(ams); } + { for (int i = 0; i < ams.size(); i++) + { AttributeMatching am = (AttributeMatching) ams.get(i); + addMapping(am); + } + } public void setAttributeMatches(Vector srcatts, Vector trgatts) { for (int i = 0; i < srcatts.size(); i++) @@ -121,14 +227,24 @@ public void setAttributeMatches(Vector srcatts, Vector trgatts) } } + public void addMapping(AttributeMatching am) + { if (attributeMappings.contains(am)) { } + else + { attributeMappings.add(am); } + } + public void addAttributeMatch(AttributeMatching am) - { attributeMappings.add(am); } + { addMapping(am); } public void addAttributeMapping(AttributeMatching am) - { attributeMappings.add(am); } + { addMapping(am); } public void addAttributeMappings(Vector ams) - { attributeMappings.addAll(ams); } + { for (int i = 0; i < ams.size(); i++) + { AttributeMatching am = (AttributeMatching) ams.get(i); + addMapping(am); + } + } public Vector getAttributeMatchings() { return attributeMappings; } @@ -148,7 +264,7 @@ public Vector boolEnumConversions(Vector names) for (int i = 0; i < attributeMappings.size(); i++) { AttributeMatching am = (AttributeMatching) attributeMappings.get(i); - res.addAll(am.boolEnumConversions(names)); + res = VectorUtil.union(res,am.boolEnumConversions(names)); } return res; } @@ -158,7 +274,7 @@ public Vector enumBoolConversions(Vector names) for (int i = 0; i < attributeMappings.size(); i++) { AttributeMatching am = (AttributeMatching) attributeMappings.get(i); - res.addAll(am.enumBoolConversions(names)); + res = VectorUtil.union(res,am.enumBoolConversions(names)); } return res; } @@ -192,8 +308,42 @@ AttributeMatching findAttributeMatch(Attribute x) return null; } // but there could be a match for x in a subclass - public boolean isUnusedSource(Attribute x) + public boolean usedInSource(Attribute x) + { for (int i = 0; i < attributeMappings.size(); i++) + { AttributeMatching am = (AttributeMatching) attributeMappings.get(i); + if (am.usedInSource(x)) + { return true; } + } + + if (condition != null && usedInCondition(x)) + { return true; } + return false; + } + + public boolean usedInCondition(Attribute x) + { Vector xs = new Vector(); + xs.add(x + ""); + Vector varsusedin = condition.variablesUsedIn(xs); + if (varsusedin.size() > 0) + { return true; } + return false; + } + + + public boolean usedAsIntermediateClass(Entity e) { for (int i = 0; i < attributeMappings.size(); i++) + { AttributeMatching am = (AttributeMatching) attributeMappings.get(i); + if (am.usedAsIntermediateClass(e)) + { return true; } + } + return false; + } + + public boolean isUnusedSource(Attribute x) + { if (condition != null && usedInCondition(x)) + { return false; } + + for (int i = 0; i < attributeMappings.size(); i++) { AttributeMatching am = (AttributeMatching) attributeMappings.get(i); if (am.unusedInSource(x)) { } @@ -203,15 +353,112 @@ public boolean isUnusedSource(Attribute x) return true; } - public boolean isUnusedTarget(Attribute x) + public boolean isUnusedTargetByName(Attribute x) { for (int i = 0; i < attributeMappings.size(); i++) { AttributeMatching am = (AttributeMatching) attributeMappings.get(i); if (am.trg.getName().equals(x.getName())) { return false; } + + Vector path = am.trg.getNavigation(); + String initialname = ""; + for (int j = 0; j < path.size(); j++) + { Attribute tp = (Attribute) path.get(j); + initialname = initialname + tp.getName(); + if (initialname.equals(x.getName())) + { return false; } + if (j < path.size() - 1) + { initialname = initialname + "."; } + } + } + return true; + } + + public boolean isUnusedTarget(Attribute x) + { for (int i = 0; i < attributeMappings.size(); i++) + { AttributeMatching am = (AttributeMatching) attributeMappings.get(i); + if (x == am.trg || x.equalByNameAndOwner(am.trg) || x.equalToReverseDirection(am.trg)) + { return false; } + + Vector path = am.trg.getNavigation(); + String initialname = ""; + for (int j = 0; j < path.size(); j++) + { Attribute tp = (Attribute) path.get(j); + if (x == tp || x.equalByNameAndOwner(tp)) + { return false; } + } } return true; } + public void checkTargetFeatureCompleteness(Vector ems, Vector thesaurus) + { Vector locals1 = trg.getAttributes(); + Vector locals3 = src.getAttributes(); + Vector added = new Vector(); + + for (int i = 0; i < locals1.size(); i++) + { Attribute tatt = (Attribute) locals1.get(i); + if (ModelMatching.isUnusedTarget(tatt,ems)) + { System.err.println("!! Unused target feature " + realtrg + "::" + tatt); + double bestmatch = 0; + Attribute smatched = null; + + for (int j = 0; j < locals3.size(); j++) + { Attribute satt = (Attribute) locals3.get(j); + double tknss = + Entity.nmsSimilarity(tatt.getName(), satt.getName(), thesaurus); + System.out.println(">>> NMS similarity of " + tatt + " and " + satt + + " = " + tknss); + if (tknss > bestmatch) + { bestmatch = tknss; + smatched = satt; + } + } + + Attribute tmatched = null; + AttributeMatching amt = null; + + for (int j = 0; j < attributeMappings.size(); j++) + { AttributeMatching am = (AttributeMatching) attributeMappings.get(j); + Attribute targatt = am.trg; + double tknss = + Entity.nmsSimilarity(tatt.getName(), targatt.getName(), thesaurus); + System.out.println(">>> NMS similarity of " + tatt + " and " + targatt + + " = " + tknss); + if (tknss > bestmatch) + { bestmatch = tknss; + tmatched = targatt; + amt = am; + } + } + + if (tmatched != null) // feature splitting + { System.out.println(">>> best match is target " + tmatched); + if (ModelMatching.compatibleType(amt.src,tatt,ems)) + { AttributeMatching newam = ModelMatching.defineFeatureSplitting(amt,tatt); + if (newam != null) + { added.add(newam); + System.out.println(">>> Adding " + newam); + } + else + { added.add(new AttributeMatching(amt.src,tatt)); + System.out.println(">>> Adding " + amt.src + " |--> " + tatt); + } + } + } + else if (smatched != null) + { System.out.println(">>> best match is source " + smatched); + if (ModelMatching.compatibleType(smatched,tatt,ems)) + { System.out.println(">>> Adding " + smatched + " |--> " + tatt); + added.add(new AttributeMatching(smatched,tatt)); + } + } + else + { System.out.println(">>> no match for " + tatt); } + } + } + addAttributeMappings(added); + } + public Vector unusedSupplierBooleans(Attribute sref, Vector ems) { // boolean attributes of sref's supplier class, which are not in any mapping @@ -221,19 +468,141 @@ public Vector unusedSupplierBooleans(Attribute sref, Vector ems) { return res; } if (stype.isEntity()) { Entity supplier = stype.getEntity(); - EntityMatching em = ModelMatching.getEntityMatching(supplier,ems); - if (em != null) - { Vector sbools = supplier.getLocalBooleanFeatures(); + Vector entmatches = ModelMatching.getEntityMatchings(supplier,ems); + for (int k = 0; k < entmatches.size(); k++) + { EntityMatching em = (EntityMatching) entmatches.get(k); + Vector sbools = supplier.getLocalBooleanFeatures(); for (int i = 0; i < sbools.size(); i++) { Attribute att = (Attribute) sbools.get(i); if (em.isUnusedSource(att) && isUnusedSource(att)) - { res.add(att); } + { if (res.contains(att)) { } + else + { res.add(att); } + } } } } return res; } + public Vector unusedSourceBooleans() + { Vector sbools = realsrc.getLocalBooleanFeatures(); + System.out.println(">>> Boolean source features: " + sbools); + Vector res = new Vector(); + + for (int i = 0; i < sbools.size(); i++) + { Attribute sbool = (Attribute) sbools.get(i); + if (isUnusedSource(sbool)) + { if (res.contains(sbool)) { } + else + { res.add(sbool); } + } + } + return res; + } + + public Vector unusedSourceEnumerations() + { Vector sbools = realsrc.getLocalEnumerationFeatures(); + System.out.println(">>> Enumeration source features: " + sbools); + Vector res = new Vector(); + + for (int i = 0; i < sbools.size(); i++) + { Attribute sbool = (Attribute) sbools.get(i); + if (isUnusedSource(sbool)) + { if (res.contains(sbool)) { } + else + { res.add(sbool); } + } + } + return res; + } + + public Vector unusedSourceStrings() + { Vector sbools = realsrc.getLocalStringFeatures(); + System.out.println(">>> String source features: " + sbools); + Vector res = new Vector(); + + for (int i = 0; i < sbools.size(); i++) + { Attribute sbool = (Attribute) sbools.get(i); + if (isUnusedSource(sbool)) + { if (res.contains(sbool)) { } + else + { res.add(sbool); } + } + } + return res; + } + + + public Vector unusedSourceConditions(Vector featuresets) + { Vector locals1 = realsrc.getLocalFeatures(); + Vector locals2 = realsrc.getNonLocalFeatures(); + + Vector res1 = new Vector(); + Vector res2 = new Vector(); + + for (int i = 0; i < locals1.size(); i++) + { Attribute sbool = (Attribute) locals1.get(i); + if (isUnusedSource(sbool)) + { res1.add(sbool); } + } + + for (int i = 0; i < locals2.size(); i++) + { Attribute sbool = (Attribute) locals2.get(i); + if (isUnusedSource(sbool)) + { res2.add(sbool); } + } + + System.out.println(">>> Unused local source features: " + res1); + System.out.println(">>> Unused non-local source features: " + res2); + + BasicExpression selfexp = new BasicExpression("self"); + selfexp.setType(new Type(realsrc)); + selfexp.setElementType(new Type(realsrc)); + + Vector res = new Vector(); + for (int i = 0; i < res1.size(); i++) + { Attribute ix = (Attribute) res1.get(i); + Type tix = ix.getType(); + Type tixe = ix.getElementType(); + if (tix != null && tix.isEntityType() && tix.getEntity() == realsrc) + { BasicExpression eix = new BasicExpression(ix); + eix.setUmlKind(Expression.ATTRIBUTE); + BinaryExpression cond = new BinaryExpression("=",selfexp,eix); + res.add(cond); + featuresets.add(ix); + } + else if (tixe != null && tixe.isEntityType() && tixe.getEntity() == realsrc) + { BasicExpression eix = new BasicExpression(ix); + eix.setUmlKind(Expression.ATTRIBUTE); + BinaryExpression cond = new BinaryExpression("->includes",eix,selfexp); + res.add(cond); + featuresets.add(ix); + } + } + + for (int i = 0; i < res2.size(); i++) + { Attribute ix = (Attribute) res2.get(i); + Type tix = ix.getType(); + Type tixe = ix.getElementType(); + if (tix != null && tix.isEntityType() && tix.getEntity() == realsrc) + { BasicExpression eix = new BasicExpression(ix); + eix.setUmlKind(Expression.ATTRIBUTE); + BinaryExpression cond = new BinaryExpression("=",selfexp,eix); + res.add(cond); + featuresets.add(ix); + } + else if (tixe != null && tixe.isEntityType() && tixe.getEntity() == realsrc) + { BasicExpression eix = new BasicExpression(ix); + eix.setUmlKind(Expression.ATTRIBUTE); + BinaryExpression cond = new BinaryExpression("->includes",eix,selfexp); + res.add(cond); + featuresets.add(ix); + } + } + return res; + } + public Vector unusedReverseReferences(Attribute sref, Vector ems) { // reference features of target of sref's supplier, unused, with reverse compatible with sref Vector res = new Vector(); @@ -242,13 +611,17 @@ public Vector unusedReverseReferences(Attribute sref, Vector ems) { return res; } if (stype.isEntity()) { Entity supplier = stype.getEntity(); - EntityMatching em = ModelMatching.getEntityMatching(supplier,ems); - if (em != null) - { Vector srefs = em.realtrg.getLocalReferenceFeatures(); - for (int i = 0; i < srefs.size(); i++) - { Attribute att = (Attribute) srefs.get(i); + Vector entmatches = ModelMatching.getEntityMatchings(supplier,ems); + for (int i = 0; i < entmatches.size(); i++) + { EntityMatching em = (EntityMatching) entmatches.get(i); + Vector srefs = em.realtrg.getLocalReferenceFeatures(); + for (int j = 0; j < srefs.size(); j++) + { Attribute att = (Attribute) srefs.get(j); if (em.isUnusedTarget(att) && ModelMatching.compatibleReverse(sref,att,ems)) - { res.add(att); } + { if (res.contains(att)) { } + else + { res.add(att); } + } } } } @@ -264,6 +637,25 @@ public Vector unusedTargetReferences(Attribute sref, Vector ems) { Attribute att = (Attribute) trefs.get(i); if (att.isMultiValued() && ModelMatching.isUnusedTarget(att,ems)) { if (ModelMatching.compatibleType(sref,att,ems)) + { if (res.contains(att)) { } + else + { res.add(att); } + } + } + } + return res; + } + + public Vector unusedMandatoryTargetReferences(Vector ems) + { // reference 1 features of realtrg, unused as target features + + Vector res = new Vector(); + Vector trefs = realtrg.getLocalReferenceFeatures(); + for (int i = 0; i < trefs.size(); i++) + { Attribute att = (Attribute) trefs.get(i); + if (att.isMandatory() && ModelMatching.isUnusedTarget(att,ems)) + { if (res.contains(att)) { } + else { res.add(att); } } } @@ -272,6 +664,12 @@ public Vector unusedTargetReferences(Attribute sref, Vector ems) public boolean isUnused(Attribute x, Vector ems) { // assume path size <= 2 + + if (condition != null) + { if (usedInCondition(x)) + { return false; } + } + Vector path = x.getNavigation(); if (path.size() <= 1) { AttributeMatching am = findAttributeMatch(x); @@ -303,6 +701,8 @@ else if (last.getEntity() != null) } return false; } // or unused if some parts are unused. + // Better to check along the path by name & owner + public Vector findCompatibleMappings(Attribute x, Vector ems) { Vector res = new Vector(); @@ -313,11 +713,17 @@ else if (am.isExpressionAssignment()) { } else if (am.isStringAssignment()) { } else if (am.src.getName().equals(x.getName())) {} else if ((am.src.getType() + "").equals(x.getType() + "")) - { res.add(am); } + { if (res.contains(am)) { } + else + { res.add(am); } + } else if (am.src.getElementType() != null && (am.src.getElementType() + "").equals( x.getElementType() + "")) - { res.add(am); } + { if (res.contains(am)) { } + else + { res.add(am); } + } else if (am.src.getElementType() != null && x.getElementType() != null && am.src.getElementType().isEntity() && x.getElementType().isEntity()) { Entity e1 = am.src.getElementType().getEntity(); @@ -326,11 +732,18 @@ else if (am.src.getElementType() != null && x.getElementType() != null && Entity e1img = ModelMatching.lookupRealMatch(e1,ems); Entity e2img = ModelMatching.lookupRealMatch(e2,ems); if (e1img == e2img) - { res.add(am); } + { if (res.contains(am)) { } + else + { res.add(am); } + } } else if ((am.trg.getType() + "").equals(x.getType() + "")) - { res.add(am); } + { if (res.contains(am)) { } + else + { res.add(am); } + } } + Entity sup = src.getSuperclass(); if (sup != null) { EntityMatching supmatch = ModelMatching.getMatching(sup,ems); @@ -367,7 +780,7 @@ else if (d1 > 0 && d1 == bestmatch) } } return best; - } + } // also use NMS public Vector findClosestNamed(Attribute x, Vector atts) { double bestmatch = 0; @@ -390,7 +803,7 @@ else if (d1 == bestmatch) { best.add(att); } } return best; - } + } // also NMS public AttributeMatching findClosestNamedPair(Vector atts1, Vector atts2) { double bestmatch = 0; @@ -424,21 +837,25 @@ else if (d1 == bestmatch) AttributeMatching am = new AttributeMatching((Attribute) bestx.get(0), (Attribute) besty.get(0)); return am; - } + } // also NMS public AttributeMatching findSuperclassMapping(Attribute x, Vector ems) { Entity sup = src.getSuperclass(); if (sup != null) - { EntityMatching supmatch = ModelMatching.getMatching(sup,ems); - if (supmatch != null) - { Vector ams = supmatch.getAttributeMatchings(); + { Vector supmatches = ModelMatching.getMatchings(sup,ems); + for (int xx = 0; xx < supmatches.size(); xx++) + { EntityMatching supmatch = (EntityMatching) supmatches.get(xx); + Vector ams = supmatch.getAttributeMatchings(); // System.out.println(supmatch.realsrc + " >> " + supmatch.realtrg + " has mappings " + ams); for (int i = 0; i < ams.size(); i++) { AttributeMatching am = (AttributeMatching) ams.get(i); if (am.src.getName().equals(x.getName())) { return am; } } - return supmatch.findSuperclassMapping(x,ems); + + AttributeMatching sm = supmatch.findSuperclassMapping(x,ems); + if (sm != null) + { return sm; } } return null; } @@ -448,17 +865,23 @@ public AttributeMatching findSuperclassMapping(Attribute x, Vector ems) public AttributeMatching findConsistentSuperclassMapping(Attribute x, Vector ems) { Entity sup = src.getSuperclass(); if (sup != null) - { EntityMatching supmatch = ModelMatching.getMatching(sup,ems); - if (supmatch != null && - (supmatch.realtrg == realtrg || Entity.isAncestor(supmatch.realtrg,realtrg))) - { Vector ams = supmatch.getAttributeMatchings(); - // System.out.println(supmatch.realsrc + " >> " + supmatch.realtrg + " has mappings " + ams); - for (int i = 0; i < ams.size(); i++) - { AttributeMatching am = (AttributeMatching) ams.get(i); - if (am.src.getName().equals(x.getName())) - { return am; } - } - return supmatch.findConsistentSuperclassMapping(x,ems); + { Vector supmatches = ModelMatching.getMatchings(sup,ems); + for (int j = 0; j < supmatches.size(); j++) + { EntityMatching supmatch = (EntityMatching) supmatches.get(j); + if (supmatch.realtrg == realtrg || + Entity.isAncestor(supmatch.realtrg,realtrg)) + { Vector ams = supmatch.getAttributeMatchings(); + // System.out.println(supmatch.realsrc + " >> " + supmatch.realtrg + " has mappings " + ams); + for (int i = 0; i < ams.size(); i++) + { AttributeMatching am = (AttributeMatching) ams.get(i); + if (am.src.getName().equals(x.getName())) + { return am; } + } + } + + AttributeMatching sm = supmatch.findConsistentSuperclassMapping(x,ems); + if (sm != null) + { return sm; } } return null; } @@ -492,7 +915,8 @@ public void removeInvalidMatchings(Vector ems) { AttributeMatching amx = (AttributeMatching) ams.get(j); if (amx.trg.getName().equals(ftarget.getName())) { String yn = - JOptionPane.showInputDialog("Remove " + realsrc + " mapping " + am + " that conflicts with " + + JOptionPane.showInputDialog("Remove " + realsrc + " mapping " + am + + " that may conflict with " + amx + " (y or n)?:"); if (yn != null && yn.equals("y")) @@ -507,7 +931,7 @@ public void removeInvalidMatchings(Vector ems) } } attributeMappings.removeAll(removed); - } + } // could also merge them boolean isConcrete() @@ -516,14 +940,21 @@ boolean isConcrete() boolean isConcreteTarget() { return trg.isConcrete(); } + public String getName() + { return realsrc.getName() + "2" + realtrg.getName(); } + public String toString() { String res = ""; if (condition == null) - { res = realsrc.getName() + " |--> " + realtrg.getName() + "\n"; } + { res = realsrc.getName() + " |--> " + realtrg.getName(); } else { res = "{ " + condition + " } " + - realsrc.getName() + " |--> " + realtrg.getName() + "\n"; + realsrc.getName() + " |--> " + realtrg.getName(); } + + if (postcondition != null) + { res = res + " { " + postcondition + " }"; } + res = res + "\n"; for (int i = 0; i < attributeMappings.size(); i++) { AttributeMatching am = (AttributeMatching) attributeMappings.get(i); @@ -607,33 +1038,64 @@ else if (am.trg != null && am.trg.getName().equals(trgreverse)) } attributeMappings.removeAll(removed); - attributeMappings.addAll(added); + addAttributeMappings(added); } - + public void createSubclassMatchings(Vector srcsubs, Vector ems) + { Vector added = new Vector(); + for (int i = 0; i < srcsubs.size(); i++) + { Entity srcsub = (Entity) srcsubs.get(i); + EntityMatching e2tent = ModelMatching.findEntityMatchingFor(srcsub, + realtrg,ems); + if (e2tent == null) + { EntityMatching emnew = new EntityMatching(srcsub,realtrg); + added.add(emnew); + } + } + ems.addAll(added); + } + public void copyAttributeMappingsToSubclasses(Vector subs, Vector ems, - Vector thesaurus, Map mymap, Vector entities) + Vector thesaurus, ModelMatching modmatch, + Vector entities) { Vector added = new Vector(); + Map mymap = modmatch.mymap; for (int i = 0; i < subs.size(); i++) { Entity sub = (Entity) subs.get(i); - EntityMatching em = ModelMatching.getEntityMatching(sub,ems); - if (em != null) - { if (realtrg == em.realtrg || Entity.isAncestor(realtrg,em.realtrg)) + Vector ematches = ModelMatching.getEntityMatchings(sub,ems); + + for (int j = 0; j < ematches.size(); j++) + { EntityMatching em = (EntityMatching) ematches.get(j); + if (realtrg == em.realtrg || Entity.isAncestor(realtrg,em.realtrg)) { System.out.println(">> Copying attribute matchings from " + realsrc + " |--> " + realtrg + " down to " + em.realsrc + " |--> " + em.realtrg); - em.copyAttributeMappings(attributeMappings,thesaurus,mymap,entities); + em.copyAttributeMappings(attributeMappings,thesaurus,modmatch,entities); } else { System.err.println(">> Target " + em.realtrg + " of " + em.realsrc + " is not subclass of " + realtrg); - // option to create a new mapping. - if (realtrg.isConcrete()) + // option to change this mapping, em, or to create a new mapping. + String ans0 = JOptionPane.showInputDialog("Change " + realsrc + " |--> " + + realtrg + " target to " + em.realtrg + + " or superclass?: (y/n) "); + if (ans0 != null && "y".equals(ans0)) + { if (em.realtrg.getSuperclass() != null && realsrc.isAbstract()) + { realtrg = em.realtrg.getSuperclass(); + // May invalidate attribute mappings + revalidateAttributeMappings(); + } + else if (em.realtrg.isConcrete()) + { realtrg = em.realtrg; + revalidateAttributeMappings(); + } + } + else if (realtrg.isConcrete()) { String ans = JOptionPane.showInputDialog("Create additional map " + sub + " |--> " + - realtrg + " (entity splitting vertical of " + sub + + realtrg + " (class splitting vertical of " + sub + ")?: (y/n) "); if (ans != null && "y".equals(ans)) { EntityMatching newe = new EntityMatching(sub,realtrg); @@ -648,7 +1110,8 @@ public void copyAttributeMappingsToSubclasses(Vector subs, Vector ems, } } } - else + + if (ematches.size() == 0) { System.err.println(">> No mapping for subclass " + sub + " of " + realsrc); if (realtrg.isConcrete()) { System.err.println(">> Creating mapping to " + realtrg + @@ -660,7 +1123,60 @@ public void copyAttributeMappingsToSubclasses(Vector subs, Vector ems, } } - ems.addAll(added); + // ems.addAll(added); + modmatch.addEntityMatchings(added,entities); + + for (int i = 0; i < subs.size(); i++) + { Entity sub = (Entity) subs.get(i); + EntityMatching em = ModelMatching.getEntityMatching(sub,ems); + if (em != null && em.realsrc != null) + { Vector subsubs = em.realsrc.getSubclasses(); + if (subsubs.size() > 0) + { em.copyAttributeMappingsToSubclasses(subsubs,ems,thesaurus,modmatch,entities); } + } + } + } // and recursively + + public void copyAttributeMappingToSubclasses(AttributeMatching amnew, Vector subs, Vector ems, + Vector thesaurus, ModelMatching modmatch, + Vector entities) + { Vector added = new Vector(); + Vector ams = new Vector(); + ams.add(amnew); + + for (int i = 0; i < subs.size(); i++) + { Entity sub = (Entity) subs.get(i); + EntityMatching em = ModelMatching.getEntityMatching(sub,ems); + if (em != null) + { if (realtrg == em.realtrg || Entity.isAncestor(realtrg,em.realtrg)) + { System.out.println(">> Copying " + amnew + " from " + + realsrc + " |--> " + realtrg + " down to " + em.realsrc + " |--> " + em.realtrg); + em.copyAttributeMappings(ams,thesaurus,modmatch,entities); + } + else + { System.err.println(">> Target " + em.realtrg + " of " + em.realsrc + + " is not subclass of " + realtrg); + + // option to change this mapping, em, or to create a new mapping. + System.out.println(">> Copying applicable attribute matchings from " + + realsrc + " |--> " + realtrg + " to " + em.realsrc + " |--> " + em.realtrg); + em.copyApplicableAttributeMappings(ams); + } + } + else + { System.err.println(">> No mapping for subclass " + sub + " of " + realsrc); + if (realtrg.isConcrete()) + { System.err.println(">> Creating mapping to " + realtrg + + " for subclass " + sub + " of " + realsrc); + EntityMatching newem = new EntityMatching(sub,realtrg); + newem.addAttributeMappings(attributeMappings); + newem.addAttributeMappings(ams); + added.add(newem); + } + } + } + + modmatch.addEntityMatchings(added,entities); for (int i = 0; i < subs.size(); i++) { Entity sub = (Entity) subs.get(i); @@ -668,14 +1184,16 @@ public void copyAttributeMappingsToSubclasses(Vector subs, Vector ems, if (em != null && em.realsrc != null) { Vector subsubs = em.realsrc.getSubclasses(); if (subsubs.size() > 0) - { em.copyAttributeMappingsToSubclasses(subsubs,ems,thesaurus,mymap,entities); } + { em.copyAttributeMappingToSubclasses(amnew,subsubs,ems,thesaurus,modmatch,entities); } } } } // and recursively - public void copyAttributeMappings(Vector ams, Vector thesaurus, Map mymap, Vector entities) + public void copyAttributeMappings(Vector ams, Vector thesaurus, + ModelMatching modmatch, Vector entities) { Vector removed = new Vector(); Vector added = new Vector(); + Map mymap = modmatch.mymap; // ams are the mappings from the superclass of src. @@ -694,7 +1212,7 @@ public void copyAttributeMappings(Vector ams, Vector thesaurus, Map mymap, Vecto double simold = amx.similarity(mymap,entities,thesaurus); double simnew = am.similarity(mymap,entities,thesaurus); - if (simnew >= simold) + if (simnew > simold) { removed.add(amx); // remove a conflicting mapping, but only if new mapping is better if (added.contains(am)) { } @@ -720,7 +1238,7 @@ else if (amx.trg != null && amx.trg.getName().equals(amtrg.getName())) } attributeMappings.removeAll(removed); - attributeMappings.addAll(added); + addAttributeMappings(added); } @@ -744,20 +1262,23 @@ public void copyApplicableAttributeMappings(Vector ams) if (amx.trg != null && amx.trg.getName().equals(amtrg.getName())) { found = true; - String ans = - JOptionPane.showInputDialog("Replace old mapping " + amx + " by " + am + "?(y/n):"); - if (ans != null && "y".equals(ans)) - { - if (amx.trg.isMultipleValued()) { } - else - { removed.add(amx); } // remove a conflicting mapping - - if (added.contains(am)) { } - else - { added.add(am); - System.out.println(">--- added mapping " + am + - " to " + realsrc + " -> " + realtrg); - } // if realtrg has the feature am.trg + if (amx.src.getName().equals(am.src.getName())) { } + else + { String ans = + JOptionPane.showInputDialog("Replace old mapping " + amx + " by " + am + "?(y/n):"); + if (ans != null && "y".equals(ans)) + { + if (amx.trg.isMultipleValued()) { } + else + { removed.add(amx); } // remove a conflicting mapping + + if (added.contains(am)) { } + else + { added.add(am); + System.out.println(">--- added mapping " + am + + " to " + realsrc + " -> " + realtrg); + } // if realtrg has the feature am.trg + } } break; } @@ -776,12 +1297,32 @@ public void copyApplicableAttributeMappings(Vector ams) } attributeMappings.removeAll(removed); - attributeMappings.addAll(added); + addAttributeMappings(added); } + public void revalidateAttributeMappings() + { Vector removed = new Vector(); + Vector added = new Vector(); - public Vector allMappingsToTarget(AttributeMatching am1, Vector removed0) - { Vector res = new Vector(); + // ams are the mappings from the superclass of src. + + for (int i = 0; i < attributeMappings.size(); i++) + { AttributeMatching am = (AttributeMatching) attributeMappings.get(i); + Attribute amsrc = am.src; + Attribute amtrg = am.trg; + + if (realtrg.isDefinedDataFeature(am.trg)) + { System.out.println(">--- " + realtrg + " has feature " + am.trg); } + else + { removed.add(am); } + } + + attributeMappings.removeAll(removed); + } + + + public Vector allMappingsToTarget(AttributeMatching am1, Vector removed0) + { Vector res = new Vector(); res.add(am1); for (int j = 0; j < attributeMappings.size(); j++) @@ -839,7 +1380,8 @@ public boolean isNeededIn(AttributeMatching am) } - public Vector analyseCorrelationPatterns(Vector ems) + public Vector analyseCorrelationPatterns(Vector ems, ModelMatching modmatch, + Vector entities, Vector types) { Vector res = new Vector(); if (srcname.equals(trgname)) @@ -912,7 +1454,7 @@ else if (am.src.getOwner() == realsrc && am.isDirectSource() && !am.isDirectTarg // excl = "exclusive"; // } - CorrelationPattern p = new CorrelationPattern(splitkind + " entity splitting", + CorrelationPattern p = new CorrelationPattern(splitkind + " class splitting", "Direct features of " + realsrc + " are split into " + tsplits.size() + " target classes " + tsplits); p.addSourceEntity(realsrc); @@ -960,7 +1502,17 @@ else if (am.src.getOwner() == realsrc && am.isDirectSource() && !am.isDirectTarg q.addSourceEntity(realsrc); q.addTargetFeature(am1.trg); if (res.contains(q)) { } else { res.add(q); } - } + } + else + { String response = + JOptionPane.showInputDialog("Enter new expression for map " + + " expression |--> " + am1.trg + + "?: (expression/null) "); + if (response != null && !"null".equals(response)) + { promptForAttributeMapping(response,entities,types, + am1,removed0,added0); + } + } } } } @@ -976,7 +1528,7 @@ else if (am.src.getOwner() == realsrc && am.isDirectSource() && !am.isDirectTarg Vector added = new Vector(); Vector removed = new Vector(); - // are there any unused attributes? + // are there any unused source attributes? for (int i = 0; i < srcatts.size(); i++) { Attribute amsrc = (Attribute) srcatts.get(i); if (isUnusedSource(amsrc) && (!realsrc.isShared() || amsrc.isSource())) @@ -1009,6 +1561,16 @@ else if (am.src.getOwner() == realsrc && am.isDirectSource() && !am.isDirectTarg added.add(newam); message = "Combined feature mapping: " + expr + " |--> " + amx.trg; } + else + { String response = + JOptionPane.showInputDialog("Enter new expression for map " + + " expression |--> " + amx.trg + + "?: (expression/null) "); + if (response != null && !"null".equals(response)) + { promptForAttributeMapping(response,entities,types, + amx,removed0,added0); + } + } } else { message = "Suggest combining with " + amx; } @@ -1026,7 +1588,9 @@ else if (am.src.getOwner() == realsrc && am.isDirectSource() && !am.isDirectTarg for (int i = 0; i < srcasts.size(); i++) { Attribute amsrc = (Attribute) srcasts.get(i); - if (isUnusedSource(amsrc) && (!realsrc.isShared() || amsrc.isSource()) && isUnused(amsrc,ems)) + if (isUnusedSource(amsrc) && + (!realsrc.isShared() || amsrc.isSource()) && + isUnused(amsrc,ems)) { String message = "No other mapped feature has the same type"; AttributeMatching amx = findConsistentSuperclassMapping(amsrc,ems); if (amx != null) @@ -1056,8 +1620,20 @@ else if (am.src.getOwner() == realsrc && am.isDirectSource() && !am.isDirectTarg if (auxvars.size() > 0) { var = (Attribute) auxvars.get(0); } AttributeMatching newam = new AttributeMatching(expr, amx.trg, var, auxvars); - added.add(newam); + if (added.contains(newam)) { } + else + { added.add(newam); } } + else + { String response = + JOptionPane.showInputDialog("Enter new expression for map " + + " expression |--> " + amx.trg + + "?: (expression/null) "); + if (response != null && !"null".equals(response)) + { promptForAttributeMapping(response,entities,types, + amx,removed0,added0); + } + } } else { message = "Suggest combining with " + amx; } @@ -1076,9 +1652,9 @@ else if (am.src.getOwner() == realsrc && am.isDirectSource() && !am.isDirectTarg // Also identify unused target features attributeMappings.removeAll(removed0); - attributeMappings.addAll(added0); + addAttributeMappings(added0); attributeMappings.removeAll(removed); - attributeMappings.addAll(added); + addAttributeMappings(added); for (int i = 0; i < srcatts.size(); i++) { Attribute amsrc = (Attribute) srcatts.get(i); @@ -1115,9 +1691,14 @@ else if (am.src.getOwner() == realsrc && am.isDirectSource() && !am.isDirectTarg var$.setElementType(amsrc.getElementType()); amnew.elementVariable = var$; amnew.addAuxVariable(amsrc); - attributeMappings.add(amnew); + addAttributeMapping(amnew); + CorrelationPattern introSelect = new CorrelationPattern("Introduce select", + "Select of unused boolean " + sel + " mapped to " + fref); + if (res.contains(introSelect)) { } + else + { res.add(introSelect); } } - } + } // also try unused supplier enumerations } } } @@ -1158,6 +1739,11 @@ else if (am.src.getOwner() == realsrc && am.isDirectSource() && !am.isDirectTarg amnew.elementVariable = var$; amnew.addAuxVariable(amsrc); emx.addAttributeMapping(amnew); + CorrelationPattern reversedad = new CorrelationPattern("Reversed association direction", + "Reversed source association " + rev + " maps to target " + fref); + if (res.contains(reversedad)) { } + else + { res.add(reversedad); } } // should check it is valid, ie., rev is feature of supplier, fref of emx.realtrg } @@ -1173,7 +1759,7 @@ else if (am.isStringAssignment()) { } else if (am.isExpressionAssignment()) { } else if (am.isDirect()) { Vector patts = am.analyseCorrelationPatterns(src,trg, - realsrc,realtrg,this,ems); + realsrc,realtrg,this,ems,modmatch,entities); res.addAll(patts); } } // but avoid duplicates @@ -1233,6 +1819,49 @@ else if (trgsubs.size() > srcsubs.size()) } + private void promptForAttributeMapping(String response, Vector entities, Vector types, + AttributeMatching am1, Vector removed0, Vector added0) + { Compiler2 cc = new Compiler2(); + cc.nospacelexicalanalysis(response); + Expression newexp = cc.parseExpression(); + + if (newexp != null) + { Vector contexts = new Vector(); + contexts.add(realsrc); + newexp.typeCheck(types,entities,contexts,new Vector()); + Vector auxvars = newexp.allAttributesUsedIn(); + + // System.out.println(">>>> attributes used in " + newexp + " are: " + auxvars); + + Attribute var = null; + if (auxvars.size() > 0) + { var = (Attribute) auxvars.get(0); } + + AttributeMatching newam; + if ((newexp instanceof BasicExpression) && (var + "").equals(newexp + "")) + { newam = new AttributeMatching(var, am1.trg); } + else + { newam = new AttributeMatching(newexp, am1.trg, var, auxvars); } + + removed0.add(am1); + added0.add(newam); + } + } + + public void removeDuplicateMappings() + { Vector res = new Vector(); + for (int i = 0; i < attributeMappings.size(); i++) + { AttributeMatching am = (AttributeMatching) attributeMappings.get(i); + if (res.contains(am)) { } + else + { res.add(am); } + } + attributeMappings.clear(); + attributeMappings.addAll(res); + } + + + String qvtrule1(Vector ems) { // if (src == trg) { return ""; } @@ -1263,7 +1892,7 @@ String qvtrule1(Vector ems) if (srcsup != null) { for (int i = 0; i < ems.size(); i++) { EntityMatching em = (EntityMatching) ems.get(i); - if (em.realsrc == srcsup) + if (em.realsrc == srcsup && Entity.isDescendant(realtrg,em.realtrg)) { String ssname = srcsup.getName(); String stname = em.realtrg.getName(); overrides = " overrides " + ssname + "2" + stname + " "; @@ -1274,6 +1903,10 @@ String qvtrule1(Vector ems) res = res + overrides + "\n"; res = res + " { checkonly domain source " + srcvar + " : " + srcent + " {};\n"; res = res + " enforce domain target " + trgvar + " : " + trgent + " {};\n"; + + // Should include attribute mappings that are not in any superclass rule & of 1-mult and of + // value type + if (condition != null) { Expression cexp = condition.addReference(srcv, new Type(realsrc)); res = res + " when { " + cexp + " }\n"; @@ -1282,6 +1915,173 @@ String qvtrule1(Vector ems) return res; } + String qvtrule1bx(Vector ems) + { // if (src == trg) { return ""; } + + String srcvar = srcname.toLowerCase() + "x"; + BasicExpression srcv = new BasicExpression(srcvar); + String srcent = srcname.substring(0,srcname.length()-1); + + if (realsrc != null) + { srcent = realsrc.getName(); + srcv.setType(new Type(realsrc)); + srcv.setElementType(new Type(realsrc)); + } + + String trgvar = trgname.toLowerCase() + "x"; + BasicExpression trgv = new BasicExpression(trgvar); + + String trgent = trgname.substring(0,trgname.length()-1); + + if (realtrg != null) + { trgent = realtrg.getName(); + trgv.setType(new Type(realtrg)); + trgv.setElementType(new Type(realtrg)); + } + + Vector localams = new Vector(); + localams.addAll(attributeMappings); + + String overrides = ""; + String res = " top relation " + srcent + "2" + trgent; + if (src.isConcrete()) + { res = " " + res; } + else + { res = " abstract" + res; } + + Entity srcsup = realsrc.getSuperclass(); + if (srcsup != null) + { EntityMatching em = ModelMatching.getAncestorMatching(srcsup,realtrg,ems); + if (em != null) + { String ssname = em.realsrc.getName(); + String stname = em.realtrg.getName(); + overrides = " overrides " + ssname + "2" + stname + " "; + localams.removeAll(em.attributeMappings); + } + } + res = res + overrides + "\n"; + + Attribute srcroot = new Attribute(srcvar, new Type(realsrc), ModelElement.INTERNAL); + Attribute trgroot = new Attribute(trgvar, new Type(realtrg), ModelElement.INTERNAL); + + ObjectTemplateExp sourceObjectTemplate = new ObjectTemplateExp(srcroot,realsrc); + ObjectTemplateExp targetObjectTemplate = new ObjectTemplateExp(trgroot,realtrg); + + Vector whereclause = new Vector(); + + for (int i = 0; i < localams.size(); i++) + { AttributeMatching am = (AttributeMatching) localams.get(i); + + if (am.isStringAssignment()) + { Vector reverseassignments = am.inverts(realsrc,realtrg,ems); + Vector auxvars = am.getAuxVariables(); + // Expression val = (Expression) am.srcvalue.clone(); + for (int j = 0; j < auxvars.size(); j++) + { Attribute av = (Attribute) auxvars.get(j); + Vector avpath = new Vector(); + Vector avnavigation = av.getNavigation(); + if (avnavigation.size() == 0) + { avpath.add(av); } + else + { avpath.addAll(avnavigation); } + // String avdata = AttributeMatching.dataname(srcvar,avpath); + am.sourceequation(srcvar,avpath, + sourceObjectTemplate); + // val = val.substituteEq(av + "", new BasicExpression(avdata)); + // System.out.println("TARGET NAME " + am.trg + " " + av + " " + val); + } + Expression srcexpr = am.srcvalue.addReference(new BasicExpression(srcroot), + new Type(realsrc)); + whereclause.add(trgv + "." + am.trg + " = " + srcexpr); + /* Vector trgpath = new Vector(); + if (am.trg.getNavigation().size() == 0) + { trgpath.add(am.trg); } + else + { trgpath.addAll(am.trg.getNavigation()); } + am.targetequation(trgvar,trgpath,val+"",targetObjectTemplate); + for (int j = 0; j < auxvars.size(); j++) + { Attribute av = (Attribute) auxvars.get(j); + Vector avpath = new Vector(); + Vector avnavigation = av.getNavigation(); + if (avnavigation.size() == 0) + { avpath.add(av); } + else + { avpath.addAll(avnavigation); } + + am.sourceequation(srcvar,avpath, + sourceObjectTemplate); + String srcdata = am.sourcedataname(srcvar); + Vector trgpath = new Vector(); + if (am.trg.getNavigation().size() == 0) + { trgpath.add(am.trg); } + else + { trgpath.addAll(am.trg.getNavigation()); } + + am.targetequation(trgvar,trgpath,val+"", + targetObjectTemplate); + am.targetequationbx(srcv,trgv,trgvar,srcdata, + targetObjectTemplate,whereclause); */ + for (int j = 0; j < reverseassignments.size(); j++) + { AttributeMatching invam = (AttributeMatching) reverseassignments.get(j); + whereclause.add(trgv + "." + invam.trg + " = " + srcv + "." + invam.src); + } + } + else if (am.isValueAssignment()) + { Expression sval = + am.srcvalue.addReference(new BasicExpression(srcroot), + new Type(realsrc)); + String trgeq = am.trg + " = " + sval; + // targetObjectTemplate.addPTI(am.trg,sval); + Vector trgpath = new Vector(); + if (am.trg.getNavigation().size() == 0) + { trgpath.add(am.trg); } + else + { trgpath.addAll(am.trg.getNavigation()); } + am.targetequation(trgvar,trgpath,sval + "",targetObjectTemplate); + } + else if (am.isExpressionAssignment()) + { } + else if (am.isDirect()) + { String srceq = ""; + String trgeq = ""; + String srcdata = am.sourcedataname(srcvar); + + EntityMatching emx = am.isObjectMatch(ems); + if (emx == null) + { srceq = am.sourceequation(srcvar,sourceObjectTemplate); + trgeq = am.targetequationbx(srcv,trgv,trgvar,srcdata,targetObjectTemplate,whereclause); + } + } + } + + if (condition != null) + { Expression cexp = condition.addReference(srcv, new Type(realsrc)); + sourceObjectTemplate.addWhere(cexp); + } + + res = res + " { checkonly domain source " + sourceObjectTemplate + ";\n"; + res = res + " enforce domain target " + targetObjectTemplate + ";\n"; + + // Should include attribute mappings that are not in any superclass rule & of 1-mult and of + // value type + + + + if (whereclause.size() > 0) + { res = res + " where {\n"; + for (int i = 0; i < whereclause.size(); i++) + { res = res + " " + whereclause.get(i); + if (i < whereclause.size() - 1) + { res = res + " and\n"; } + else + { res = res + "\n"; }; + } + res = res + " }\n"; + } + res = res + " }\n"; + return res; + } + String qvtrule2(Vector ems) { // if (src == trg) { return ""; } @@ -1346,8 +2146,12 @@ String qvtrule2(Vector ems) { Vector auxvars = am.getAuxVariables(); for (int j = 0; j < auxvars.size(); j++) { Attribute av = (Attribute) auxvars.get(j); - Vector avpath = new Vector(); - avpath.add(av); + Vector avpath = new Vector(); + Vector avnavigation = av.getNavigation(); + if (avnavigation.size() == 0) + { avpath.add(av); } + else + { avpath.addAll(avnavigation); } // String avdata = AttributeMatching.dataname(srcvar,avpath); am.sourceequation(srcvar,avpath,sourceObjectTemplate); } @@ -1356,21 +2160,28 @@ else if (am.isExpressionAssignment()) { Expression expr = am.getExpression(); Expression instantiatedexpr = expr.addReference(new BasicExpression(srcroot), new Type(realsrc)); - Expression inst = new BasicExpression(am.getElementVariable()); - Expression test = new BinaryExpression("->includes", instantiatedexpr, inst); - sourceObjectTemplate.addWhere(test); - // and add a domain am.elementVariable : E1 { }; - auxdomains = auxdomains + - " domain source " + inst + " : " + expr.getElementType() + " {};\n"; - - /* Vector avpath = new Vector(); - if (am.trg.getNavigation().size() == 0) - { avpath.add(am.trg); } + if ("self".equals(expr + "")) + { } + else if (expr.isMultiple()) + { Expression inst = new BasicExpression(am.getElementVariable()); + Expression test = new BinaryExpression("->includes", instantiatedexpr, inst); + sourceObjectTemplate.addWhere(test); + // and add a domain am.elementVariable : E1 { }; + auxdomains = auxdomains + + " domain source " + inst + " : " + expr.getElementType() + " {};\n"; + } else - { avpath.addAll(am.trg.getNavigation()); } - String avdata = AttributeMatching.dataname(trgvar,avpath); */ - String whenc = am.whenClause(trgvar,ems,whens); - whenclauses.add(whenc); + { Expression inst = new BasicExpression(am.getElementVariable()); + Expression test = new BinaryExpression("=", inst, instantiatedexpr); + sourceObjectTemplate.addWhere(test); + // and add a domain am.elementVariable : E1 { }; + auxdomains = auxdomains + + " domain source " + inst + " : " + expr.getElementType() + " {};\n"; + } + + String whenc = am.whenClause(trgvar,instantiatedexpr + "",ems,whens); + if (whenc != null && whenc.trim().length() > 0 && !("true".equals(whenc))) + { whenclauses.add(whenc); } } else if (am.isValueAssignment()) { } @@ -1387,17 +2198,6 @@ else if (am.isDirect()) } else { srceq = am.sourceequation(srcvar,sourceObjectTemplate); } - - if (scount > 0) - { if (srceq.length() > 0) - { srcbody = srcbody + ", " + srceq; - scount++; - } - } - else if (srceq.length() > 0) - { srcbody = srceq; - scount++; - } } } @@ -1423,103 +2223,76 @@ else if (srceq.length() > 0) for (int j = 0; j < auxvars.size(); j++) { Attribute av = (Attribute) auxvars.get(j); Vector avpath = new Vector(); - avpath.add(av); + Vector avnavigation = av.getNavigation(); + if (avnavigation.size() == 0) + { avpath.add(av); } + else + { avpath.addAll(avnavigation); } String avdata = AttributeMatching.dataname(srcvar,avpath); val = val.substituteEq(av + "", new BasicExpression(avdata)); // System.out.println("TARGET NAME " + am.trg + " " + av + " " + val); } - targetObjectTemplate.addPTI(am.trg,val); + // targetObjectTemplate.addPTI(am.trg,val); + Vector trgpath = new Vector(); + if (am.trg.getNavigation().size() == 0) + { trgpath.add(am.trg); } + else + { trgpath.addAll(am.trg.getNavigation()); } + am.targetequation(trgvar,trgpath,val+"",targetObjectTemplate); } else if (am.isExpressionAssignment()) - { am.targetequation(trgvar,"",targetObjectTemplate); } + { if (am.srcvalue.isMultiple()) + { am.targetequation(trgvar,"",targetObjectTemplate); } + else + { am.targetequation(trgvar, "" + am.getElementVariable(), + targetObjectTemplate); + } + } else if (am.isValueAssignment()) { Expression sval = am.srcvalue.addReference(new BasicExpression(srcroot), new Type(realsrc)); String trgeq = am.trg + " = " + sval; - targetObjectTemplate.addPTI(am.trg,sval); + // targetObjectTemplate.addPTI(am.trg,sval); + Vector trgpath = new Vector(); + if (am.trg.getNavigation().size() == 0) + { trgpath.add(am.trg); } + else + { trgpath.addAll(am.trg.getNavigation()); } + am.targetequation(trgvar,trgpath,sval + "",targetObjectTemplate); } else if (am.isDirect()) { String srceq = ""; String trgeq = ""; String srcdata = am.sourcedataname(srcvar); - trgeq = am.targetequation(trgvar,srcdata,targetObjectTemplate); - - if (tcount > 0) - { if (trgeq.length() > 0) - { trgbody = trgbody + ", " + trgeq; - tcount++; - } - } - else if (trgeq.length() > 0) - { trgbody = trgeq; - tcount++; - } + trgeq = am.targetequation(trgvar,srcdata,targetObjectTemplate); } } - // Attribute self = new Attribute("self",new Type(realsrc),ModelElement.INTERNAL); - // self.setType(new Type(realsrc)); - // self.setElementType(new Type(realsrc)); - // System.out.println("QVT-O Target code: " + targetObjectTemplate.toQVTO(self,whens)); - // System.out.println("UML-RSDS Target code: " + - // realsrc + ":: " + - // targetObjectTemplate.toUMLRSDSroot(realsrc.getName()) + " & " + - // sourceObjectTemplate.toUMLRSDSantecedent() + " => \n" + - // " " + targetObjectTemplate.toUMLRSDS(whens)); - - /* String sobjs = ""; - Vector srcobjs = objTemplates.elements; - for (int h = 0; h < srcobjs.size(); h++) - { Maplet maplet = (Maplet) srcobjs.get(h); - String sobj = (String) maplet.source; - Vector sdefn = (Vector) maplet.dest; - sobjs = sobjs + " " + sobj + " { "; - for (int g = 0; g < sdefn.size(); g++) - { String sdef = (String) sdefn.get(g); - sobjs = sobjs + sdef; - if (g < sdefn.size() - 1) - { sobjs = sobjs + ", "; } - } - sobjs = sobjs + " }"; - if (h < srcobjs.size() - 1) - { sobjs = sobjs + ", "; } - } */ - - /* String tobjs = ""; - Vector trgobjs = tExps.elements; - for (int h = 0; h < trgobjs.size(); h++) - { Maplet maplet = (Maplet) trgobjs.get(h); - String tobj = (String) maplet.source; - Vector tdefn = (Vector) maplet.dest; - tobjs = tobjs + " " + tobj + " { "; - for (int g = 0; g < tdefn.size(); g++) - { String tdef = (String) tdefn.get(g); - tobjs = tobjs + tdef; - if (g < tdefn.size() - 1) - { tobjs = tobjs + ", "; } - } - tobjs = tobjs + " }"; - if (h < trgobjs.size() - 1) - { tobjs = tobjs + ", "; } - } */ - - /* if (scount > 0 && sobjs.length() > 0) - { srcbody = srcbody + ", " + sobjs; } */ - - /* if (tcount > 0 && tobjs.length() > 0) - { trgbody = trgbody + ", " + tobjs; } */ + if (postcondition != null) + { Expression post = postcondition.addReference(new BasicExpression(trgvar),new Type(realtrg)); + targetObjectTemplate.addWhere(post); + } String res = " top relation Map" + srcent + "2" + trgent + "\n"; res = res + " { " + auxdomains + " checkonly domain source \n " + sourceObjectTemplate + ";\n"; // srcvar + " : " + srcent + " { " + srcbody + " };\n"; res = res + " enforce domain target \n " + targetObjectTemplate + ";\n"; // trgvar + " : " + trgent + " { " + trgbody + " };\n"; - res = res + " when {\n "; + res = res + " when {\n "; + + boolean previous = false; for (int k = 0; k < whenclauses.size(); k++) { String w = (String) whenclauses.get(k); - res = res + w; - if (k < whenclauses.size() - 1) - { res = res + " and\n "; } + if ("true".equals(w)) { } + else if ("".equals(w)) { } + else + { if (previous) + { res = res + " and\n " + w; } + else + { res = res + w; + previous = true; + } + } } res = res + " }\n"; res = res + " }\n"; @@ -1530,78 +2303,281 @@ else if (trgeq.length() > 0) return res; } // and when for the objects that are referenced. - String umlrsdsrule1() - { if (src == trg) { return ""; } + String qvtrule2bx(Vector ems) + { // if (src == trg) { return ""; } + + if (attributeMappings.size() == 0) + { return ""; } String srcvar = srcname.toLowerCase() + "x"; + BasicExpression srcv = new BasicExpression(srcvar); String srcent = srcname.substring(0,srcname.length()-1); String trgvar = trgname.toLowerCase() + "x"; String trgent = trgname.substring(0,trgname.length()-1); if (realsrc != null) - { srcent = realsrc.getName(); } + { srcent = realsrc.getName(); + srcv.setType(new Type(realsrc)); + srcv.setElementType(new Type(realsrc)); + } + if (realtrg != null) { trgent = realtrg.getName(); } - String srcid = srcent.toLowerCase() + "Id"; - String trgid = trgent.toLowerCase() + "Id"; + String srcbody = ""; + String trgbody = ""; - String res = srcent + "::\n"; - if (condition != null) - { res = res + " " + condition + " =>\n "; } - res = res + " " + trgent + "->exists( " + trgvar + " | "; - res = res + trgvar + "." + trgid + " = " + srcid + " )\n"; - res = res + "\n"; - return res; - } + int scount = 0; + int tcount = 0; + + int clausecount = 0; + + Vector whenclauses = new Vector(); + whenclauses.add(srcent + "2" + trgent + "(" + srcvar + "," + trgvar + ")"); - String umlrsdsrule2(Vector ems) - { // if (src == trg) { return ""; } + // Map objTemplates = new Map(); // String -> Vector(String) + // Map tExps = new Map(); - String srcent = ""; - if (realsrc != null) - { srcent = realsrc.getName(); } - else - { srcent = srcname.substring(0,srcname.length()-1); } + Attribute srcroot = new Attribute(srcvar, new Type(realsrc), ModelElement.INTERNAL); + Attribute trgroot = new Attribute(trgvar, new Type(realtrg), ModelElement.INTERNAL); - String trgent = ""; - if (realtrg != null) - { trgent = realtrg.getName(); } - else - { trgent = trgname.substring(0,trgname.length()-1); } + ObjectTemplateExp sourceObjectTemplate = new ObjectTemplateExp(srcroot,realsrc); + ObjectTemplateExp targetObjectTemplate = new ObjectTemplateExp(trgroot,realtrg); + String auxdomains = ""; - String srcvar = srcname.toLowerCase() + "x"; - String trgvar = trgname.toLowerCase() + "x"; + Vector srcnames = new Vector(); + for (int i = 0; i < attributeMappings.size(); i++) + { AttributeMatching am = (AttributeMatching) attributeMappings.get(i); + srcnames.add(am.src.getName()); + } + + Vector ams1 = (Vector) Ocl.sortedBy(attributeMappings, srcnames); + Map whens = new Map(); + for (int i = 0; i < ams1.size(); i++) + { AttributeMatching am = (AttributeMatching) ams1.get(i); - String srcid = srcent.toLowerCase() + "Id"; - String trgid = trgent.toLowerCase() + "Id"; + if (am.isStringAssignment()) { } + else if (am.isExpressionAssignment()) + { Expression expr = am.getExpression(); + Expression instantiatedexpr = expr.addReference(new BasicExpression(srcroot), + new Type(realsrc)); + if ("self".equals(expr + "")) + { } + else if (expr.isMultiple()) + { Expression inst = new BasicExpression(am.getElementVariable()); + Expression test = new BinaryExpression("->includes", instantiatedexpr, inst); + sourceObjectTemplate.addWhere(test); + // and add a domain am.elementVariable : E1 { }; + auxdomains = auxdomains + + " domain source " + inst + " : " + expr.getElementType() + " {};\n"; + } + else + { Expression inst = new BasicExpression(am.getElementVariable()); + Expression test = new BinaryExpression("=", inst, instantiatedexpr); + sourceObjectTemplate.addWhere(test); + // and add a domain am.elementVariable : E1 { }; + auxdomains = auxdomains + + " domain source " + inst + " : " + expr.getElementType() + " {};\n"; + } - String targetbody = ""; - String remainder = ""; + String whenc = am.whenClause(trgvar,instantiatedexpr + "",ems,whens); + if (whenc != null && whenc.trim().length() > 0 && !("true".equals(whenc))) + { whenclauses.add(whenc); } + clausecount++; + } + else if (am.isValueAssignment()) + { } + else if (am.isDirect()) + { String srceq = ""; + String srcdata = am.sourcedataname(srcvar); + + EntityMatching emx = am.isObjectMatch(ems); + if (emx != null) + { am.dependsOn = emx; + String whenc = am.whenClause(emx,srcvar,trgvar,whens); + whenclauses.add(whenc); + srceq = am.sourceequation(srcvar,sourceObjectTemplate); + clausecount++; + } + } + } - Vector created = new Vector(); + if (clausecount == 0) + { return ""; } + + if (condition != null) + { Expression cexp = condition.addReference(srcv, new Type(realsrc)); + sourceObjectTemplate.addWhere(cexp); + } Vector trgnames = new Vector(); for (int i = 0; i < attributeMappings.size(); i++) { AttributeMatching am = (AttributeMatching) attributeMappings.get(i); trgnames.add(am.trg.getName()); } - Vector ams2 = (Vector) Ocl.sortedBy(attributeMappings, trgnames); + // System.out.println(">>> Source template = " + sourceObjectTemplate); + // Collections.sort(trgnames); + // System.out.println(">>> Source names = " + srcnames); + + Vector ams2 = (Vector) Ocl.sortedBy(attributeMappings, trgnames); for (int i = 0; i < ams2.size(); i++) { AttributeMatching am = (AttributeMatching) ams2.get(i); - if (am.isStringAssignment()) - { String trgeq = trgvar + "." + am.trg + " = " + am.srcvalue; - targetbody = targetbody + " & " + trgeq; - } - else if (am.isExpressionAssignment() && am.isDirectTarget()) - { Type srcvaltype = am.srcvalue.getElementType(); - if (srcvaltype != null) + + + if (am.isStringAssignment()) { } + else if (am.isExpressionAssignment()) + { if (am.srcvalue.isMultiple()) + { am.targetequation(trgvar,"",targetObjectTemplate); } + else + { am.targetequation(trgvar, "" + am.getElementVariable(), + targetObjectTemplate); + } + } + else if (am.isDirect()) + { EntityMatching emx = am.isObjectMatch(ems); + if (emx != null) + { String srceq = ""; + String trgeq = ""; + String srcdata = am.sourcedataname(srcvar); + trgeq = am.targetequation(trgvar,srcdata,targetObjectTemplate); + } + } + } + + if (postcondition != null) + { Expression post = postcondition.addReference(new BasicExpression(trgvar),new Type(realtrg)); + targetObjectTemplate.addWhere(post); + } + + String res = " top relation Map" + srcent + "2" + trgent + "\n"; + res = res + " { " + auxdomains + " checkonly domain source \n " + sourceObjectTemplate + ";\n"; + // srcvar + " : " + srcent + " { " + srcbody + " };\n"; + res = res + " enforce domain target \n " + targetObjectTemplate + ";\n"; + // trgvar + " : " + trgent + " { " + trgbody + " };\n"; + res = res + " when {\n "; + + boolean previous = false; + for (int k = 0; k < whenclauses.size(); k++) + { String w = (String) whenclauses.get(k); + if ("true".equals(w)) { } + else if ("".equals(w)) { } + else + { if (previous) + { res = res + " and\n " + w; } + else + { res = res + w; + previous = true; + } + } + } + res = res + " }\n"; + res = res + " }\n"; + + sourceTemplate = sourceObjectTemplate; + targetTemplate = targetObjectTemplate; + + return res; + } // and when for the objects that are referenced. + + String umlrsdsrule1() + { if (src == trg) { return ""; } + + String srcvar = srcname.toLowerCase() + "x"; + String srcent = srcname.substring(0,srcname.length()-1); + String trgvar = trgname.toLowerCase() + "x"; + String trgent = trgname.substring(0,trgname.length()-1); + + if (realsrc != null) + { srcent = realsrc.getName(); } + if (realtrg != null) + { trgent = realtrg.getName(); } + + String srcid = srcent.toLowerCase() + "Id"; + String trgid = trgent.toLowerCase() + "Id"; + Attribute srcpk = realsrc.getPrincipalPK(); + if (srcpk != null) + { srcid = srcpk.getName(); } + Attribute trgpk = realtrg.getPrincipalPK(); + if (trgpk != null) + { trgid = trgpk.getName(); } + + String res = srcent + "::\n"; + if (condition != null) + { res = res + " " + condition + " =>\n "; } + res = res + " " + trgent + "->exists( " + trgvar + " | "; + res = res + trgvar + "." + trgid + " = " + srcid + " )\n"; + res = res + "\n"; + return res; + } + + String umlrsdsrule2(Vector ems) + { // if (src == trg) { return ""; } + + String srcent = ""; + if (realsrc != null) + { srcent = realsrc.getName(); } + else + { srcent = srcname.substring(0,srcname.length()-1); } + + String trgent = ""; + if (realtrg != null) + { trgent = realtrg.getName(); } + else + { trgent = trgname.substring(0,trgname.length()-1); } + + String srcvar = srcname.toLowerCase() + "x"; + String trgvar = trgname.toLowerCase() + "x"; + + + String srcid = srcent.toLowerCase() + "Id"; + String trgid = trgent.toLowerCase() + "Id"; + Attribute srcpk = realsrc.getPrincipalPK(); + if (srcpk != null) + { srcid = srcpk.getName(); } + Attribute trgpk = realtrg.getPrincipalPK(); + if (trgpk != null) + { trgid = trgpk.getName(); } + + String targetbody = ""; + String remainder = ""; + + Vector created = new Vector(); + + Vector trgnames = new Vector(); + for (int i = 0; i < attributeMappings.size(); i++) + { AttributeMatching am = (AttributeMatching) attributeMappings.get(i); + trgnames.add(am.trg.getName()); + } + Vector ams2 = (Vector) Ocl.sortedBy(attributeMappings, trgnames); + + + for (int i = 0; i < ams2.size(); i++) + { AttributeMatching am = (AttributeMatching) ams2.get(i); + if (am.isStringAssignment() && am.isDirectTarget()) + { String trgeq = trgvar + "." + am.trg + " = " + am.srcvalue; + targetbody = targetbody + " & " + trgeq; + } + else if (am.isExpressionAssignment() && am.isDirectTarget()) + { Type srcvaltype = am.srcvalue.getElementType(); + if (srcvaltype != null && srcvaltype.isEntityType()) { String e1Id = srcvaltype.getName().toLowerCase() + "Id"; - Expression srcids = - new BinaryExpression("->collect", am.srcvalue, new BasicExpression(e1Id)); + Attribute e1pk = srcvaltype.getEntity().getPrincipalPK(); + if (e1pk != null) + { e1Id = e1pk.getName(); } + + Expression srcids = null; + if (am.srcvalue.isMultipleValued()) + { am.srcvalue.setBrackets(true); + srcids = new BinaryExpression("->collect", am.srcvalue, + new BasicExpression(e1Id)); + } + else + { srcids = new BasicExpression(e1Id); + ((BasicExpression) srcids).setObjectRef(am.srcvalue); + } String trgeq = trgvar + "." + am.trg + " = " + am.trg.getElementType() + "[" + srcids + "]"; targetbody = targetbody + " & " + trgeq; @@ -1612,7 +2588,7 @@ else if (am.isExpressionAssignment() && am.isDirectTarget()) } updateCreated(am.trg.getNavigation(),created); } - else if (am.isValueAssignment()) + else if (am.isValueAssignment() && am.isDirectTarget()) { String trgeq = trgvar + "." + am.trg + " = " + am.srcvalue; targetbody = targetbody + " & " + trgeq; } @@ -1628,10 +2604,10 @@ else if (am.isDirectTarget()) } } - String trgvar1 = trgent.toLowerCase() + "_x"; for (int j = 0; j < ams2.size(); j++) { AttributeMatching am = (AttributeMatching) ams2.get(j); + String trgvar1 = trgent.toLowerCase() + "$" + j; if (!am.isDirectTarget() && am.isExpressionAssignment()) { remainder = remainder + srcent + "::\n"; @@ -1662,6 +2638,17 @@ else if (src == trg) res = res + trgvar + "." + trgid + " = " + srcid + targetbody + " )\n"; } res = res + "\n\n" + remainder; + + String trgvar2 = trgent.toLowerCase() + "$x"; + + if (postcondition != null) + { Expression post = postcondition.addReference(new BasicExpression(trgvar2),new Type(realtrg)); + String postconstraint = srcent + "::\n"; + postconstraint = postconstraint + " " + trgvar2 + " = " + trgent + "[" + srcid + "] "; + postconstraint = postconstraint + " => (" + post + ")\n\n"; + res = res + "\n\n" + postconstraint; + } + return res; } // use targetTemplate to rationalise the remainder. @@ -1674,7 +2661,7 @@ public String qvtomain1() if (realtrg != null) { trgent = realtrg.getName(); } - return " in.objects[" + srcent + "]->map " + srcent + "2" + trgent + "();\n"; + return " src.objects()[" + srcent + "]->map " + srcent + "2" + trgent + "();\n"; } public String qvtomain2() @@ -1688,7 +2675,7 @@ public String qvtomain2() if (realtrg != null) { trgent = realtrg.getName(); } - return " in.objects[" + srcent + "]->map map" + srcent + "2" + trgent + "();\n"; + return " src.objects()[" + srcent + "]->map map" + srcent + "2" + trgent + "();\n"; } public String qvtorule1() @@ -1728,7 +2715,7 @@ public String qvtodisjunctsrule(Vector ems) { trgent = realtrg.getName(); } String subs = ""; - Vector subclasses = src.getSubclasses(); + Vector subclasses = realsrc.getSubclasses(); int subcount = 0; @@ -1742,12 +2729,15 @@ public String qvtodisjunctsrule(Vector ems) if (subname.endsWith("$")) { srcsub = subname.substring(0,subname.length()-1); } - Entity tsub = ModelMatching.lookupMatch(sub,ems); - if (tsub != null) - { String tsubname = tsub.getName(); + Vector submatches = ModelMatching.findSpecialisedMatchingsBySourceTarget(sub,realtrg,ems); + for (int j = 0; j < submatches.size(); j++) + { EntityMatching submatch = (EntityMatching) submatches.get(j); + Entity tsub = submatch.realtrg; + String tsubname = tsub.getName(); String trgsub = tsubname; - if (tsubname.endsWith("$")) - { trgsub = tsubname.substring(0,tsubname.length()-1); } + srcsub = submatch.realsrc.getName(); + // if (tsubname.endsWith("$")) + // { trgsub = tsubname.substring(0,tsubname.length()-1); } String subopname = srcsub + "::" + srcsub + "2" + trgsub; @@ -1816,6 +2806,10 @@ public String qvtorule2(Vector ems) Vector ams2 = (Vector) Ocl.sortedBy(attributeMappings, trgnames); + BasicExpression tvar = new BasicExpression("result"); + tvar.setType(new Type(realtrg)); + tvar.setElementType(new Type(realtrg)); + String targetbody = ""; for (int i = 0; i < ams2.size(); i++) { AttributeMatching am = (AttributeMatching) ams2.get(i); @@ -1830,29 +2824,46 @@ public String qvtorule2(Vector ems) val = val.substituteEq(av + "", new BasicExpression(avdata)); // System.out.println("TARGET NAME " + am.trg + " " + av + " " + val); } - targetbody = targetbody + "\n " + - "result." + am.trg + " := " + val; + if (am.isDirectTarget()) + { targetbody = targetbody + "\n " + + "result." + am.trg + " := " + val + ";"; + } + else + { String trgeq = am.targetequationQVTO(tvar,val,ems,created); + updateCreated(am.trg.getNavigation(), created); + targetbody = targetbody + "\n " + trgeq; + } } else if (am.isExpressionAssignment() && am.isDirectTarget()) { Expression srcinst = am.srcvalue.addReference(new BasicExpression("self"), new Type(realsrc)); - String trgeq = "result." + am.trg + " := (" + srcinst + ").resolve();"; + Type srctype = am.srcvalue.getType(); + String trgeq = ""; + if (srctype != null && srctype.isValueType()) + { trgeq = "result." + am.trg + " := " + srcinst + ";"; } + else + { trgeq = "result." + am.trg + " := (" + srcinst + ").resolve();"; } + updateCreated(am.trg.getNavigation(), created); targetbody = targetbody + "\n " + trgeq; } else if (am.isValueAssignment()) { Expression sval = am.srcvalue.addReference(new BasicExpression("self"), new Type(realsrc)); - String trgeq = "result." + am.trg + " := " + sval + ";"; - targetbody = targetbody + "\n " + trgeq; + if (am.isDirectTarget()) + { targetbody = targetbody + "\n " + + "result." + am.trg + " := " + sval + ";"; + } + else + { String trgeq = am.targetequationQVTO(tvar,sval,ems,created); + updateCreated(am.trg.getNavigation(), created); + targetbody = targetbody + "\n " + trgeq; + } } else if (am.isDirect()) { String srceq = ""; String trgeq = ""; // String srcdata = am.sourcedataname(srcvar); - BasicExpression tvar = new BasicExpression("result"); - tvar.setType(new Type(realtrg)); - tvar.setElementType(new Type(realtrg)); Expression svar; if (am.isExpressionAssignment()) { svar = am.srcvalue.addReference(new BasicExpression("self"), @@ -1890,8 +2901,10 @@ else if (am.isDirect()) " " + targetbody + "\n}\n"; } - String atlrule(Vector ems) + String atlrule(Vector ems, Vector secondaryRules) { // if (src == trg) { return ""; } + // Only produce rules for primary rules. Secondary rules are put into + // primary rule as a new OutPattern. Vector allnewrules = new Vector(); Vector allnewclauses = new Vector(); @@ -1935,7 +2948,7 @@ String atlrule(Vector ems) { AttributeMatching am = (AttributeMatching) ams2.get(i); String trgeq = " "; - if (am.isStringAssignment()) + if (am.isStringAssignment() && am.isDirectTarget()) { Expression newval = am.srcvalue.addReference(new BasicExpression(srcvar), new Type(realsrc)); trgeq = trgeq + am.trg + " <- " + newval; @@ -1944,6 +2957,19 @@ String atlrule(Vector ems) else if (am.isExpressionAssignment() && am.isDirectTarget()) { Expression newval = am.srcvalue.addReference(new BasicExpression(srcvar), new Type(realsrc)); + if ("self".equals(am.srcvalue + "")) + { Type tet = am.trg.getElementType(); + if (tet != null && tet.isEntityType()) + { Entity tent = tet.getEntity(); + String tvar = tent.getName().toLowerCase() + "_x"; + EntityMatching em = ModelMatching.findEntityMatchingFor(realsrc,tent,ems); + if (em != null && em.isSecondary()) + { } + else + { tvar = "thisModule.resolveTemp(" + srcvar + ", '" + tvar + "')"; } + newval = new BasicExpression(tvar); + } + } trgeq = trgeq + am.trg + " <- " + newval; targetbody.add(trgeq); @@ -1955,11 +2981,13 @@ else if (am.isExpressionAssignment() && am.isDirectTarget()) implementedBy.put(cpathatt.getName(), am.trg); } else if (am.isValueAssignment() && am.isDirectTarget()) - { trgeq = trgeq + am.trg + " <- " + am.srcvalue; + { Expression sval = am.srcvalue.addReference(new BasicExpression(srcvar), + new Type(realsrc)); + trgeq = trgeq + am.trg + " <- " + sval; targetbody.add(trgeq); } else if (am.isDirectTarget()) - { trgeq = trgeq + am.atldirecttarget(srcvar); + { trgeq = trgeq + am.atldirecttarget(srcvar,ems); targetbody.add(trgeq); Vector cpath = am.trg.getNavigation(); if (cpath.size() == 0) @@ -1992,7 +3020,171 @@ else if (am.isDirectTarget()) res = res + " { from " + srcvar + " : MM1!" + srcent; if (condition != null) - { res = res + " ( " + condition + " )\n"; } + { res = res + " ( " + condition.addReference(new BasicExpression(srcvar), + new Type(realsrc)) + " )\n"; } + else + { res = res + "\n"; } + + res = res + " to " + trgvar + " : MM2!" + trgent + "\n"; + + if (targetbody.size() == 0) + { } + else + { res = res + " ( "; + for (int y = 0; y < targetbody.size()-1; y++) + { res = res + targetbody.get(y) + ",\n "; } + res = res + targetbody.get(targetbody.size()-1) + " )"; + } + + for (int i = 0; i < secondaryRules.size(); i++) + { EntityMatching emsub = (EntityMatching) secondaryRules.get(i); + emsub.atlruleSubordinate(ems,allnewrules,allnewclauses,allnewdo); + } + + for (int i = 0; i < allnewclauses.size(); i++) + { OutPatternElement newclause = (OutPatternElement) allnewclauses.get(i); + res = res + ",\n " + newclause; + } + + if (allnewdo.size() > 0) + { res = res + "\n " + + " do {\n "; + for (int d = 0; d < allnewdo.size(); d++) + { String ds = (String) allnewdo.get(d); + res = res + ds + "\n "; + } + res = res + " }"; + } + + res = res + "\n }\n\n"; + + for (int j = 0; j < allnewrules.size(); j++) + { MatchedRule newrule = (MatchedRule) allnewrules.get(j); + res = res + newrule + "\n\n"; + } + + return res; + } + + + String atlruleSubordinate(Vector ems, Vector allnewrules, + Vector allnewclauses, Vector allnewdo) + { // if (src == trg) { return ""; } + // Secondary rules are put into + // primary rule as a new OutPatternElement. + + String srcent = ""; + if (realsrc != null) + { srcent = realsrc.getName(); } + else + { srcent = srcname.substring(0,srcname.length()-1); } + + String trgent = ""; + if (realtrg != null) + { trgent = realtrg.getName(); } + else + { trgent = trgname.substring(0,trgname.length()-1); } + + String srcvar = srcent.toLowerCase() + "_x"; + String trgvar = trgent.toLowerCase() + "_x"; + + if (srcvar.equals(trgvar)) + { trgvar = trgvar + "_x"; } + + Vector targetbody = new Vector(); + String remainder = ""; + + Vector created = new Vector(); + + Vector trgnames = new Vector(); + for (int i = 0; i < attributeMappings.size(); i++) + { AttributeMatching am = (AttributeMatching) attributeMappings.get(i); + trgnames.add(am.trg.getName()); + } + Vector ams2 = (Vector) Ocl.sortedBy(attributeMappings, trgnames); + + Attribute trgatt = new Attribute(trgvar, new Type(realtrg), ModelElement.INTERNAL); + OutPatternElement ope = new OutPatternElement(trgatt); + allnewclauses.add(ope); // primary clause + + java.util.Map implementedBy = new java.util.HashMap(); + // for each path in created, either an ATL OutPatternElement or an Attribute + + for (int i = 0; i < ams2.size(); i++) + { AttributeMatching am = (AttributeMatching) ams2.get(i); + String trgeq = " "; + + if (am.isStringAssignment() && am.isDirectTarget()) + { Expression newval = am.srcvalue.addReference(new BasicExpression(srcvar), + new Type(realsrc)); + // trgeq = trgeq + am.trg + " <- " + newval; + // targetbody.add(trgeq); + Binding bres2 = new Binding(am.trg + "", newval); + ope.addBinding(bres2); + } + else if (am.isExpressionAssignment() && am.isDirectTarget()) + { Expression newval = am.srcvalue.addReference(new BasicExpression(srcvar), + new Type(realsrc)); + + // trgeq = trgeq + am.trg + " <- " + newval; + // targetbody.add(trgeq); + Binding bres2 = new Binding(am.trg + "", newval); + ope.addBinding(bres2); + Vector cpath = am.trg.getNavigation(); + if (cpath.size() == 0) + { cpath.add(am.trg); } + updateCreated(cpath,created); + Attribute cpathatt = new Attribute(cpath); + implementedBy.put(cpathatt.getName(), am.trg); + } + else if (am.isValueAssignment() && am.isDirectTarget()) + { Expression sval = am.srcvalue.addReference(new BasicExpression(srcvar), + new Type(realsrc)); + // trgeq = trgeq + am.trg + " <- " + sval; + Binding bres2 = new Binding(am.trg + "", sval); + ope.addBinding(bres2); + // targetbody.add(trgeq); + } + else if (am.isDirectTarget()) + { // trgeq = trgeq + am.atldirecttarget(srcvar,ems); + // targetbody.add(trgeq); + + Binding bres2 = am.atldirectbinding(srcvar,ems); + ope.addBinding(bres2); + Vector cpath = am.trg.getNavigation(); + if (cpath.size() == 0) + { cpath.add(am.trg); } + updateCreated(cpath,created); + Attribute cpathatt = new Attribute(cpath); + implementedBy.put(cpathatt.getName(), am.trg); + } + else // composed target + { Vector newclauses = new Vector(); // of OutPatternElement + Vector newrules = new Vector(); // of MatchedRule + Vector newdo = new Vector(); // of String + Binding cbind = + am.atlcomposedtarget(newclauses,newrules,newdo,srcvar,trgvar, + realsrc,created,implementedBy); + if (cbind != null) + { // trgeq = trgeq + cbind; + // targetbody.add(trgeq); + ope.addBinding(cbind); + } + allnewrules.addAll(newrules); + allnewclauses.addAll(newclauses); + allnewdo.addAll(newdo); + updateCreated(am.trg.getNavigation(),created); + } + + // else case of composed target + } + + String res = " rule " + srcent + "2" + trgent + "\n"; + res = res + " { from " + srcvar + " : MM1!" + srcent; + + if (condition != null) + { res = res + " ( " + condition.addReference(new BasicExpression(srcvar), + new Type(realsrc)) + " )\n"; } else { res = res + "\n"; } @@ -2029,6 +3221,199 @@ else if (am.isDirectTarget()) res = res + newrule + "\n\n"; } + return res; + } + + + TransformationRule etlrule(Vector ems, Vector auxrules) + { // if (src == trg) { return ""; } + + EntityMatching extending = null; + if (realsrc != null && realsrc.getSuperclass() != null) + { EntityMatching supermatch = + ModelMatching.findSuperclassMatchingBySourceTarget(realsrc.getSuperclass(),realtrg,ems); + if (supermatch != null) + { extending = supermatch; + // System.out.println(">> Super-rule of " + getName() + " is " + extending.getName()); + } + } + + Vector allnewrules = new Vector(); // lazy rules or operations + Vector allnewclauses = new Vector(); // additional outputs for this rule + Vector allnewdo = new Vector(); // additional code + + String srcent = ""; + if (realsrc != null) + { srcent = realsrc.getName(); } + else + { srcent = srcname.substring(0,srcname.length()-1); } + + String trgent = ""; + if (realtrg != null) + { trgent = realtrg.getName(); } + else + { trgent = trgname.substring(0,trgname.length()-1); } + + String srcvar = srcent.toLowerCase() + "_x"; + String trgvar = trgent.toLowerCase() + "_x"; + + if (srcvar.equals(trgvar)) + { trgvar = trgvar + "_x"; } + + Attribute trgatt = new Attribute(trgvar, new Type(realtrg), ModelElement.INTERNAL); + + Vector targetbody = new Vector(); + String remainder = ""; + + Vector created = new Vector(); + + Vector trgnames = new Vector(); + for (int i = 0; i < attributeMappings.size(); i++) + { AttributeMatching am = (AttributeMatching) attributeMappings.get(i); + trgnames.add(am.trg.getName()); + } + Vector ams2 = (Vector) Ocl.sortedBy(attributeMappings, trgnames); + // remove all matchings in extending. + if (extending != null) + { ams2.removeAll(extending.attributeMappings); } + + java.util.Map implementedBy = new java.util.HashMap(); + // for each path in created, either an ATL OutPatternElement or an Attribute + + for (int i = 0; i < ams2.size(); i++) + { AttributeMatching am = (AttributeMatching) ams2.get(i); + String trgeq = " "; + Statement assign; + BasicExpression directtarget = new BasicExpression(am.trg); + directtarget.setObjectRef(new BasicExpression(trgatt)); + + if (am.isStringAssignment()) + { Expression newval = am.srcvalue.addReference(new BasicExpression(srcvar), + new Type(realsrc)); + // trgeq = trgeq + am.trg + " <- " + newval; + assign = new AssignStatement(directtarget, newval); + targetbody.add(assign); + } + else if (am.isExpressionAssignment() && am.isDirectTarget()) + { Expression newval = am.srcvalue.addReference(new BasicExpression(srcvar), + new Type(realsrc)); + newval.setType(am.srcvalue.getType()); + newval.setElementType(am.srcvalue.getElementType()); + + Expression targetval = newval.etlEquivalent(am.trg,ems); + + // trgeq = trgeq + am.trg + " <- " + newval; + + assign = new AssignStatement(directtarget, targetval); + targetbody.add(assign); + + Vector cpath = am.trg.getNavigation(); + if (cpath.size() == 0) + { cpath.add(am.trg); } + updateCreated(cpath,created); + Attribute cpathatt = new Attribute(cpath); + implementedBy.put(cpathatt.getName(), am.trg); + } + else if (am.isValueAssignment() && am.isDirectTarget()) + { // trgeq = trgeq + am.trg + " <- " + am.srcvalue; + Expression newval = am.srcvalue.addReference(new BasicExpression(srcvar), + new Type(realsrc)); + newval.setType(am.srcvalue.getType()); + newval.setElementType(am.srcvalue.getElementType()); + + assign = new AssignStatement(directtarget, newval); + targetbody.add(assign); + } + else if (am.isDirectTarget()) + { // trgeq = trgeq + am.atldirecttarget(srcvar,ems); + assign = am.etldirecttarget(srcvar, directtarget,ems); + targetbody.add(assign); + + Vector cpath = am.trg.getNavigation(); + if (cpath.size() == 0) + { cpath.add(am.trg); } + updateCreated(cpath,created); + Attribute cpathatt = new Attribute(cpath); + implementedBy.put(cpathatt.getName(), am.trg); + } + else if (am.isExpressionAssignment()) // composed target + { Expression newval = am.srcvalue.addReference(new BasicExpression(srcvar), + new Type(realsrc)); + newval.setType(am.srcvalue.getType()); + newval.setElementType(am.srcvalue.getElementType()); + + // System.out.println(">> Instantiated source expression is: " + newval); + // Expression targetval = newval.etlEquivalent(am.trg,ems); + + // trgeq = trgeq + am.trg + " <- " + newval; + + // assign = new AssignStatement(directtarget, targetval); + // targetbody.add(assign); + + Vector newclauses = new Vector(); // of OutPatternElement + Vector newrules = new Vector(); // of MatchedRule + Vector newdo = new Vector(); // of Statement + Statement cbind = + am.etlcomposedtarget(newclauses,newrules,newdo,srcvar,trgvar, + realsrc,created,implementedBy,ems); + if (cbind != null) + { targetbody.add(cbind); } + allnewrules.addAll(newrules); + allnewclauses.addAll(newclauses); + targetbody.addAll(newdo); + + Vector cpath = am.trg.getNavigation(); + if (cpath.size() == 0) + { cpath.add(am.trg); } + updateCreated(cpath,created); + Attribute cpathatt = new Attribute(cpath); + implementedBy.put(cpathatt.getName(), am.trg); + } + else // composed target + { Vector newclauses = new Vector(); // of OutPatternElement + Vector newrules = new Vector(); // of MatchedRule + Vector newdo = new Vector(); // of Statement + Statement cbind = + am.etlcomposedtarget(newclauses,newrules,newdo,srcvar,trgvar, + realsrc,created,implementedBy,ems); + if (cbind != null) + { targetbody.add(cbind); } + allnewrules.addAll(newrules); + allnewclauses.addAll(newclauses); + targetbody.addAll(newdo); + updateCreated(am.trg.getNavigation(),created); + } + + // else case of composed target + } + + TransformationRule res = new TransformationRule(srcent + "2" + trgent,false,false); + Attribute srcatt = new Attribute(srcvar, new Type(realsrc), ModelElement.INTERNAL); + res.setSource(srcatt); + + if (realsrc != null && realsrc.isAbstract()) + { res.setAbstract(true); } + + if (extending != null) + { res.setExtends(new TransformationRule(extending)); } + + if (condition != null) + { Expression cond = condition.addReference(new BasicExpression(srcvar), + new Type(realsrc)); + res.setGuard(cond); + } + + res.addTarget(trgatt); + + + for (int i = 0; i < allnewclauses.size(); i++) + { OutPatternElement newclause = (OutPatternElement) allnewclauses.get(i); + res.addClause(newclause); + } + res.addBody(new SequenceStatement(targetbody)); + + auxrules.addAll(allnewrules); + return res; } // use targetTemplate to rationalise the remainder. @@ -2045,6 +3430,29 @@ private void updateCreated(Vector path, Vector created) } } } - + + public void checkModel(ModelSpecification mod) + { // For each feature mapping f |--> g, checks for each + // ex : E and corresponding fx : F, that ex.f = fx.g in + // the model. + + Vector srcobjects = mod.getObjects(realsrc.getName()); + Vector trgobjects = mod.getObjects(realtrg.getName()); + // Assume corresponding ones are in the same order + + for (int i = 0; i < attributeMappings.size(); i++) + { AttributeMatching am = (AttributeMatching) attributeMappings.get(i); + if (am.isDirectSource() && am.isDirectTarget()) + { Attribute satt = am.src; + Attribute tatt = am.trg; + if (satt.isNumeric() && tatt.isNumeric()) + { am.checkModel(mod,srcobjects,trgobjects); } + else if (satt.isString() && tatt.isString()) + { am.checkModel(mod,srcobjects,trgobjects); } + else if (satt.isCollection() && tatt.isCollection()) + { am.checkModel(mod,srcobjects,trgobjects); } + } + } + } } diff --git a/EtlModule.java b/EtlModule.java index dec6717e..aab826b3 100644 --- a/EtlModule.java +++ b/EtlModule.java @@ -37,11 +37,25 @@ public void addRule(TransformationRule r) { // if (r.isPrimary()) // { transformationRules.add(0,r); } // else + if (r == null) { } + else { transformationRules.add(r); } } + public void addRules(Vector rs) + { for (int i = 0; i < rs.size(); i++) + { TransformationRule tr = (TransformationRule) rs.get(i); + addRule(tr); + } + } + public void addOperation(BehaviouralFeature bf) - { operations.add(bf); } + { if (bf != null) + { operations.add(bf); } + } + + public void addOperations(Vector ops) + { operations.addAll(ops); } public void addAttribute(Attribute att) { attributes.add(att); } @@ -62,24 +76,31 @@ else if (ob instanceof BehaviouralFeature) public String toString() - { String res = "module " + name + "\n"; + { String res = "-- module " + name + "\r\n"; for (int i = 0; i < pre.size(); i++) { res = res + pre.get(i); } for (int j = 0; j < operations.size(); j++) { BehaviouralFeature bf = (BehaviouralFeature) operations.get(j); Entity context = bf.getEntity(); - res = res + "operation " + context + " " + bf.getSignature() + "\n" + - "{ " + bf.getActivity() + " }\n"; + if (context != null) + { res = res + "operation " + context + " " + bf.getSignature(); } + else + { res = res + "operation " + bf.getSignature(); } + Type restype = bf.getResultType(); + if (restype != null) + { res = res + " : " + restype; } + res = res + "\n" + + "{ " + (bf.getActivity()).toEtl() + " }\r\n\r\n"; } for (int i = 0; i < transformationRules.size(); i++) - { res = res + transformationRules.get(i); } + { res = res + transformationRules.get(i) + " \r\n\r\n"; } for (int i = 0; i < post.size(); i++) { res = res + post.get(i); } - return res + "\n"; + return res + "\r\n"; } public boolean typeCheck(Vector types, Vector entities, Vector contexts, Vector env) diff --git a/Expression.java b/Expression.java index 7a6207a8..f33ed182 100644 --- a/Expression.java +++ b/Expression.java @@ -76,6 +76,7 @@ abstract class Expression operators.add("=>"); operators.add("#"); operators.add("or"); + operators.add("xor"); operators.add("&"); } @@ -166,8 +167,16 @@ public Expression removeFirstConjunct() public Type getType() { return type; } + public boolean isMap() + { if (type != null && type.getName().equals("Map")) + { return true; } + return false; + } + public int getKind() { return umlkind; } + public int getMultiplicity() { return multiplicity; } + public void setUmlKind(int k) { umlkind = k; } @@ -295,10 +304,46 @@ public static void saveOperators(PrintWriter out) } } + public Expression etlEquivalent(Attribute trg, Vector ems) + { if (type == null) + { return this; } + if (trg == null) + { return this; } + + Entity sent = type.getEntity(); + if (sent == null && elementType != null) + { sent = elementType.getEntity(); } + + if (trg.getType() != null && trg.getType().isEntityType()) + { Entity tent = trg.getType().getEntity(); + EntityMatching em = ModelMatching.findEntityMatchingFor(sent,tent,ems); + if (em != null) + { return new BasicExpression("(" + this + ").equivalent('" + em.realsrc + "2" + + em.realtrg + "')"); + } + return new BasicExpression("(" + this + ").equivalent()"); + } + else if (Type.isEntityCollection(trg.getType())) + { Entity tent = trg.getElementType().getEntity(); + EntityMatching em = ModelMatching.findEntityMatchingFor(sent,tent,ems); + if (em != null) + { return new BasicExpression("(" + this + ").equivalent('" + em.realsrc + "2" + + em.realtrg + "')"); + } + return new BasicExpression("(" + this + ").equivalent()"); + } + else + { return this; } + } + + public abstract Expression definedness(); public abstract Expression determinate(); + public abstract Expression removePrestate(); + + public static Statement iterationLoop(Expression var, Expression range, Statement body) { BinaryExpression test = new BinaryExpression(":", var, range); WhileStatement ws = new WhileStatement(test, body); @@ -420,6 +465,25 @@ public String unwrapCSharp(String se) return se; // can't unwrap -- for strings or objects } + public static String unwrapSwift(String se, Type t) + { if (t == null) + { return se; } // should never happen + String tname = t.getName(); + if (tname.equals("double")) + { return "Double(" + se + ")"; } + if (tname.equals("boolean")) + { return "Bool(" + se + ")"; } + if (tname.equals("int")) + { return "Int(" + se + ")"; } + if (tname.equals("long")) + { return "Int(" + se + ")"; } + if (t.isEnumerated()) + { return tname + "(" + se + ")"; } + // for enumerated + return se; // can't unwrap -- for strings or objects + } + + public abstract Expression skolemize(Expression sourceVar, java.util.Map env); public Vector topLevelSplit(String d) @@ -603,6 +667,8 @@ public Vector allFeatureUses(Vector features) public abstract Vector allFeaturesUsedIn(); + public abstract Vector allAttributesUsedIn(); + public abstract Vector allOperationsUsedIn(); public abstract Vector equivalentsUsedIn(); @@ -1308,6 +1374,10 @@ public static Expression simplifyExistsAnd(final Expression e1, { Expression res1 = simplifyExistsAnd(be1.right, e2); return new BinaryExpression("#", be1.left, res1); } + else if ("#LC".equals(be1.operator)) + { Expression res1 = simplifyExistsAnd(be1.right, e2); + return new BinaryExpression("#LC", be1.left, res1); + } else if ("&".equals(be1.operator)) { Expression res1 = simplifyExistsAnd(be1.right, e2); return simplifyExistsAnd(be1.left, res1); @@ -1454,6 +1524,9 @@ else if (op.equals("!")) res.setBrackets(true); return res; } + else if (op.equals("->includesAll")) + { return new BinaryExpression("/<:",be.right,be.left); } + String nop = negateOp(be.operator); if (!(nop.equals(be.operator))) @@ -1542,7 +1615,26 @@ public Vector splitToCond0Cond1(Vector conds, Vector pars, Vector qvars1, Vector public Vector splitToCond0Cond1Pred(Vector conds, Vector pars, Vector qvars1, Vector lvars1, Vector allvars, Vector allpreds) - { return conds; } // all formulae in antecedent should be binary + // { return conds; } + { Expression cond0 = (Expression) conds.get(0); + Expression cond1 = (Expression) conds.get(1); + Vector res = new Vector(); + // System.out.println("Split conds on: " + this); + + Expression c1; + if (cond1 == null) + { c1 = this; } + else + { c1 = new BinaryExpression("&",cond1,this); } + res.add(cond0); + res.add(c1); + allvars.add(this); + allpreds.add(this); + // System.out.println("Added condition: " + this); + + return res; + } + public Vector splitToTCondPost(Vector tvars, Vector conds) { return conds; } // all formulae in antecedent should be binary diff --git a/IOSAppGenerator.java b/IOSAppGenerator.java new file mode 100644 index 00000000..4b32b8df --- /dev/null +++ b/IOSAppGenerator.java @@ -0,0 +1,370 @@ +import java.util.Vector; +import java.io.*; + + +public class IOSAppGenerator extends AppGenerator +{ + + public void modelFacade(Vector usecases, CGSpec cgs, Vector entities, Vector types, PrintWriter out) + { // String ename = e.getName(); + // Vector atts = e.getAttributes(); + + // String evc = ename + "ViewController"; + // String evo = ename + "ValueObject"; + // String resvo = ename.toLowerCase() + "_vo"; + // String populateResult = createVOStatement(e,atts); + + out.println("import Foundation"); + out.println("import Glibc"); + out.println(""); + out.println("class ModelFacade"); + out.println("{ static instance : ModelFacade = nil"); + // if e is persistent, include a Dbi + out.println(); + out.println(" static func getInstance() -> ModelFacade"); + out.println(" { if (instance == nil) { instance = ModelFacade() }"); + out.println(" return instance }"); + out.println(); + + for (int i = 0; i < entities.size(); i++) + { Entity ent = (Entity) entities.get(i); + if (ent.isDerived()) { } + else + { String ename = ent.getName(); + out.println(" var current" + ename + " : " + ename + "VO = nil"); + out.println(); + out.println(" var current" + + ename + "s : [" + ename + "VO] = [" + ename + "]()"); + out.println(); + } + } + + // System.out.println("import Foundation"); + // System.out.println("import Glibc"); + // System.out.println(""); + // System.out.println("class ModelFacade"); + // System.out.println("{ "); + + /* String extractatts = ""; + for (int x = 0; x < atts.size(); x++) + { Attribute att = (Attribute) atts.get(x); + Type atype = att.getType(); + if (atype != null) + { extractatts = extractatts + " var " + att + " : " + atype.getSwift() + " = vo." + att + "\n"; + } + } */ + + // System.out.println(usecases); + + for (int y = 0; y < usecases.size(); y++) + { UseCase uc = (UseCase) usecases.get(y); + Vector pars = uc.getParameters(); + Attribute res = uc.getResultParameter(); + String partext = ""; + for (int i = 0; i < pars.size(); i++) + { Attribute par = (Attribute) pars.get(i); + Type partype = par.getType(); + partext = partext + par.getName() + " : " + partype.getSwift(); + if (i < pars.size()-1) + { partext = partext + ", "; } + } + out.print(" func " + uc.getName() + "(" + partext + ")"); + if (res != null) + { out.println(" -> " + res.getType().getSwift()); } + else + { out.println(); } + + out.println(" { "); + if (res != null) + { out.println(" var result : " + res.getType().getSwift()); } + + // out.println(extractatts); + out.println(uc.cgActivity(cgs,entities,types)); + // out.println(uc.cg(cgs)); + // System.out.println(" func " + uc.getName() + "(_ vo : " + evo + ") : " + evo); + // System.out.println(" { "); + // System.out.println(extractatts); + + // out.println(uc.cgActivity(cgs,entities,types)); + // out.println(populateResult); + // out.println(" return " + resvo); + if (res != null) + { out.println(" return result"); } + + out.println(" }"); + out.println(); + + // String act = uc.activity.cg(cgs); + // System.out.println(uc.cgActivity(cgs,entities,types)); + // System.out.println(populateResult); + // System.out.println(" return " + resvo); + // System.out.println(" }"); + } + + out.println(); + + for (int j = 0; j < entities.size(); j++) + { Entity ee = (Entity) entities.get(j); + if (ee.isDerived()) { continue; } + + String item = ee.getName(); + out.println(" func list" + item + "() -> [" + item + "VO]"); + out.println(" { // current" + item + "s = dbi.list" + item + "()"); + out.println(" return current" + item + "s"); + out.println(" }"); + out.println(); + + out.println(" func stringList" + item + "() -> [String]"); + out.println(" { // current" + item + "s = dbi.list" + item + "()"); + out.println(" var res : [String] = [String]()"); + out.println(" for (i,x) in current" + item + "s.enumerated()"); + out.println(" { var _item : " + item + "VO = current" + item + "s[i]"); + out.println(" res.append(_item + \"\")"); + out.println(" }"); + out.println(" return res"); + out.println(" }"); + out.println(); + + Attribute key = ee.getPrincipalPK(); + if (key != null) + { Vector atts = ee.getAttributes(); + out.println(" func get" + item + "ByPK(_val : String) -> " + item); + out.println(" { // var _res : [" + item + "VO] = dbi.searchBy" + item + key + "(_val)"); + out.println(" if (_res.count == 0)"); + out.println(" { return nil }"); + out.println(" else"); + out.println(" { var _vo : " + item + "VO = _res[0]"); + out.println(" var _itemx : " + item + " = " + item + "(_val)"); + for (int k = 0; k < atts.size(); k++) + { Attribute att = (Attribute) atts.get(k); + String aname = att.getName(); + out.println(" _itemx." + aname + " = _vo." + aname); + } + out.println(" return _itemx"); + out.println(" }"); + out.println(" }"); + out.println(); + } + + out.println(" func setSelected" + item + "(_x : " + item + "VO)"); + out.println(" { current" + item + " = _x }"); + out.println(); + + out.println(" func setSelected" + item + "(i : Int)"); + out.println(" { if (i < current" + item + "s.count)"); + out.println(" { current" + item + " = current" + item + "s[i] }"); + out.println(" }"); + out.println(); + + out.println(" func getSelected" + item + "() -> " + item + "VO"); + out.println(" { return current" + item + " }"); + out.println(); + + out.println(" func edit" + item + "(_x : " + item + "VO)"); + out.println(" { // dbi.edit" + item + "(_x) "); + out.println(" current" + item + " = _x"); + out.println(" }"); + out.println(); + + out.println(" func create" + item + "(_x : " + item + "VO)"); + out.println(" { // dbi.create" + item + "(_x)"); + out.println(" current" + item + " = _x"); + out.println(" }"); + out.println(); + + out.println(" func delete" + item + "(_id : String)"); + out.println(" { // dbi.delete" + item + "(_id)"); + out.println(" current" + item + " = nil"); + out.println(" }"); + } + + out.println("}"); + // System.out.println("}"); + } + + public String createVOStatement(Entity e, Vector atts) + { String ename = e.getName(); + // String evc = ename + "ViewController"; + String vo = ename.toLowerCase() + "_vo"; + String evo = ename + "VO"; + String attlist = ""; + for (int x = 0; x < atts.size(); x++) + { Attribute att = (Attribute) atts.get(x); + String aname = att.getName(); + attlist = attlist + aname; + if (x < atts.size()-1) + { attlist = attlist + ","; } + } + + String res = " var " + vo + " : " + evo + " = " + evo + "(" + attlist + ")"; + return res; + } + + public void singlePageApp(UseCase uc, CGSpec cgs, PrintWriter out) + { String ucname = uc.getName(); + String evc = ucname + "ViewController"; + // String evo = ename + "ValueObject"; + // String vo = evo.toLowerCase(); + String resvo = "result"; + String restype = ""; + String ebean = "ModelFacade"; + String bean = ebean.toLowerCase(); + Vector atts = uc.getParameters(); + Attribute res = uc.getResultParameter(); + + // String evocreate = createVOStatement(e,atts); + + out.println("import UIKit"); + out.println(); + out.println("class " + evc + " : UIViewController"); + out.println("{"); + out.println(" var " + bean + " : " + ebean + " = " + ebean + ".getInstance()"); + out.println(); + + String parlist = ""; + for (int x = 0; x < atts.size(); x++) + { Attribute att = (Attribute) atts.get(x); + // if (att.isInputAttribute()) + out.println(" @IBOutlet weak var " + att + "Input: UITextField!"); + + parlist = parlist + att.getName(); + if (x < atts.size() - 1) + { parlist = parlist + ", "; } + } + + if (res != null) + { out.println(" @IBOutlet weak var resultOutput: UILabel!"); + restype = res.getType().getSwift(); + } + out.println(); + out.println(" var userId : String = " + "\"0\""); + out.println(); + out.println(" override func viewDidLoad()"); + out.println(" { super.viewDidLoad()"); + // out.println(" self." + elist + " = " + bean + "." + getlist + "()"); + out.println(" }"); + out.println(""); + + String attdecoder = " guard "; + boolean previous = false; + String localVars = ""; + + for (int x = 0; x < atts.size(); x++) + { Attribute att = (Attribute) atts.get(x); + // if (att.isInputAttribute()) + { if (previous) + { attdecoder = attdecoder + ", "; } + attdecoder = attdecoder + " let " + att + " = " + + Expression.unwrapSwift(att + "Input.text",att.getType()); + previous = true; + } + // else + // { Type atype = att.getType(); + // if (atype != null) + // { localVars = localVars + " var " + att + " : " + atype.getSwift() + "\n"; } + // } + } + attdecoder = attdecoder + " else { return }\n"; + + String updateScreen = ""; + + // for (int x = 0; x < atts.size(); x++) + if (res != null) + { Attribute att = res; // (Attribute) atts.get(x); + // if (att.isOutput()) + { updateScreen = updateScreen + " " + att + "Output.text = String(" + att + ")"; + } + } + + // for (int y = 0; y < usecases.size(); y++) + // { UseCase uc = (UseCase) usecases.get(y); + // String ucname = uc.getName(); + out.println(" @IBAction func " + ucname + "(_ sender: Any) {"); + if (atts.size() > 0) + { out.println(attdecoder); } + // out.println(localVars); + // out.println(evocreate); + if (res != null) + { out.println(" var " + resvo + " : " + restype + " = " + bean + "." + ucname + "(" + parlist + ")"); + out.println(updateScreen); + } + else + { out.println(" " + bean + "." + ucname + "(" + parlist + ")"); } + out.println(" }"); + // } + + out.println(""); + + out.println(" override func didReceiveMemoryWarning()"); + out.println(" { super.didReceiveMemoryWarning() }"); + out.println(""); + out.println("}"); + } + +public void listViewController(Entity e, PrintWriter out) +{ String ename = e.getName(); + String evc = ename + "ListViewController"; + String evo = ename + "VO"; + String ebean = "ModelFacade"; + String bean = "model"; + Vector atts = e.getAttributes(); + String elist = ename.toLowerCase() + "List"; + String getlist = "list" + ename; + + + out.println("import UIKit"); + out.println(); + out.println("class " + evc + " : UIViewController, UITableViewDataSource, UITableViewDelegate"); + out.println("{"); + out.println(" var " + bean + " : " + ebean + " = " + ebean + ".getInstance()"); + out.println(" @IBOutlet weak var tableView: UITableView!"); + out.println(); + out.println(" var userId : String = " + "\"0\""); + out.println(" var " + elist + " : [" + evo + "] = []()"); + out.println(); + out.println(" override func viewDidLoad()"); + out.println(" { super.viewDidLoad()"); + out.println(" self." + elist + " = " + bean + "." + getlist + "()"); + out.println(" }"); + out.println(""); + out.println(" override func didReceiveMemoryWarning()"); + out.println(" { super.didReceiveMemoryWarning() }"); + out.println(""); + // For UITableViewDataSource + out.println(" func numberOfSections(in tableView: UITableView) -> Int"); + out.println(" { return 1 }"); + out.println(""); + out.println(" func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int"); + out.println(" { return self." + elist + ".count }"); + out.println(""); + out.println(""); + out.println(" func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell"); + out.println(" { let cell = self.tableView.dequeueReusableCell(withIdentifier: \"Cell\", for: indexPath)"); + out.println(""); + out.println(" if let item = self." + elist + "[indexPath.row]"); + out.println(" {"); + for (int x = 0; x < atts.size(); x++) + { Attribute att = (Attribute) atts.get(x); + if (att.isSummary()) + { String attnme = att.getName(); + out.println(" cell." + attnme + "Label?.text = item." + attnme); + } + } + out.println(" }"); + out.println(" return cell"); + out.println(" }"); + out.println(" "); + + out.println(" func tableView(_ tableView: UITableView, didSelectRowAt indexPath : IndexPath)"); + out.println(" { guard let item = " + elist + "[indexPath.row] else { return }"); + out.println(" " + bean + ".setSelected" + ename + "(item)"); + out.println(" }"); + out.println("}"); +} + + + public static void main(String[] args) + { // System.out.println(Double.MAX_VALUE); + + } +} diff --git a/Maplet.java b/Maplet.java index f99357d1..1cd180f7 100644 --- a/Maplet.java +++ b/Maplet.java @@ -163,6 +163,10 @@ public void add_element(Maplet m) { elements.addElement(m); /* assumes still a map */ } + public void add(Maplet m) + { elements.add(m); /* assumes still a map */ + } + public void add_pair(Object o1, Object o2) { Maplet mm = new Maplet(o1,o2); if (elements.contains(mm)) { } diff --git a/ModelElement.java b/ModelElement.java index cbdfecfb..663c8b28 100644 --- a/ModelElement.java +++ b/ModelElement.java @@ -13,6 +13,7 @@ * *****************************/ /* Package: Class Diagram */ +// Subclasses are: Entity, Attribute, Association, Type, BehaviouralFeature, UseCase public abstract class ModelElement implements SystemTypes { protected String name; @@ -25,6 +26,7 @@ public abstract class ModelElement implements SystemTypes public static final int INTERNAL = 3; public static final int ACT = 7; public static final int DERIVED = 5; // no set operations + public static final int SUMMARY = 8; /* role multiplicity */ public static final int QUALIFIER = -4; @@ -51,6 +53,9 @@ public String getName() public void setName(String newname) { name = newname; } + public String cg(CGSpec cgs) + { return this + ""; } + public static Vector getNames(Vector elems) { Vector res = new Vector(); for (int i = 0; i < elems.size(); i++) @@ -523,6 +528,54 @@ public static String longestCommonSuffix(String s, String t) return ""; } + public static boolean haveCommonPrefix(String s, String t) + { int n = s.length(); + int m = t.length(); + if (s.startsWith(t)) { return true; } + if (t.startsWith(s)) { return true; } + if (n < m) + { for (int i = n-1; i > 1; i--) + { String sub = s.substring(0,i); + // System.out.println(sub); + if (t.startsWith(sub)) + { return true; } + } + } + else + { for (int i = m-1; i > 1; i--) + { String sub = t.substring(0,i); + // System.out.println(sub); + if (s.startsWith(sub)) + { return true; } + } + } + return false; + } + + public static String longestCommonPrefix(String s, String t) + { int n = s.length(); + int m = t.length(); + if (s.startsWith(t)) { return t; } + if (t.startsWith(s)) { return s; } + if (n < m) + { for (int i = n-1; i > 1; i--) + { String sub = s.substring(0,i); + // System.out.println(sub); + if (t.startsWith(sub)) + { return sub; } + } + } + else + { for (int i = m-1; i > 1; i--) + { String sub = t.substring(0,i); + // System.out.println(sub); + if (s.startsWith(sub)) + { return sub; } + } + } + return ""; + } + private static void addBuffer(StringBuffer b, Vector res) { if (b != null && b.length() > 0) { res.add(b.toString()); } @@ -597,9 +650,19 @@ else if (inUpper) public static void main(String[] args) { System.out.println(longestCommonSuffix("DataType", "CType")); System.out.println(longestCommonSuffix("PTArc", "TPArc")); - System.out.println(splitIntoWords("CatTamer")); + + System.out.println(splitIntoWords("memberOf.father")); - System.out.println(longestCommonSuffix("ENamedElement", "NamedElement")); + // System.out.println(longestCommonSuffix("ENamedElement", "NamedElement")); + System.out.println(similarity("type.name.ff","type.owner.gg")); + System.out.println(similarity("owner.name.ff","type.name.gg")); + Vector v = new Vector(); + System.out.println(Entity.nmsSimilarity("type.name.ff","type.owner.gg",v)); + System.out.println(Entity.nmsSimilarity("owner.name.ff","type.name.gg",v)); + System.out.println(Entity.nmsSimilarity("father","Male",v)); + System.out.println(Entity.nmsSimilarity("mother","Female",v)); + + System.out.println(longestCommonPrefix("colour", "color")); } } diff --git a/ModelMatching.java b/ModelMatching.java index f26e152f..368e2c19 100644 --- a/ModelMatching.java +++ b/ModelMatching.java @@ -1,6 +1,7 @@ import java.util.Vector; import java.io.*; import java.util.Collections; +import javax.swing.JOptionPane; /****************************** * Copyright (c) 2003,2019 Kevin Lano @@ -60,6 +61,31 @@ public ModelMatching(Map m) } } + public void addEntityMatch(EntityMatching em, Vector entities) + { Entity s = em.realsrc; + Entity t = em.realtrg; + String sname = s.getName(); + String tname = t.getName(); + Entity s$ = (Entity) ModelElement.lookupByName(sname + "$",entities); + Entity t$ = (Entity) ModelElement.lookupByName(tname + "$",entities); + if (s$ != null && t$ != null) + { mymap.add(new Maplet(s$,t$)); + System.out.println(">> Added entity matching: >> " + s$ + " --> " + t$); + } + entitymatches.add(em); + } + + public void addEntityMatchings(Vector ems) + { entitymatches.addAll(ems); } + + public void addEntityMatchings(Vector ems, Vector entities) + { for (int i = 0; i < ems.size(); i++) + { EntityMatching em = (EntityMatching) ems.get(i); + addEntityMatch(em,entities); + } + } + + public ModelMatching invert() { Map invmm = Map.inverse(mymap); ModelMatching inv = new ModelMatching(); @@ -81,13 +107,13 @@ public ModelMatching invert() } public String toString() - { String res = "Abstract transformation: \n"; + { String res = "\n"; for (int i = 0; i < entitymatches.size(); i++) { EntityMatching em = (EntityMatching) entitymatches.get(i); // Entity s = em.realsrc; // Entity t = em.realtrg; // res = res + " " + s + " |--> " + t + "\n"; - res = res + em + "\n"; + res = res + em + "\r\n"; } return res; } @@ -206,8 +232,43 @@ public Vector enumStringConversions() return res; } + public Vector enumConversionFunctionsETL(Vector enumconversions, Vector thesaurus) + { Vector res = new Vector(); + + for (int i = 0; i < enumconversions.size(); i++) + { Maplet conv = (Maplet) enumconversions.get(i); + Type e1 = (Type) conv.source; + Type e2 = (Type) conv.dest; + BehaviouralFeature tconv = Type.enumConversionFunctionETL(e1,e2,thesaurus); + res.add(tconv); + } + return res; + } + + public Vector enumStringConversionFunctionsETL(Vector enumconversions, Vector thesaurus) + { Vector res = new Vector(); + + for (int i = 0; i < enumconversions.size(); i++) + { Type e1 = (Type) enumconversions.get(i); + BehaviouralFeature tconv = Type.enumStringConversionFunctionETL(e1); + res.add(tconv); + } + return res; + } + + public Vector stringEnumConversionFunctionsETL(Vector enumconversions, Vector thesaurus) + { Vector res = new Vector(); + + for (int i = 0; i < enumconversions.size(); i++) + { Type e1 = (Type) enumconversions.get(i); + BehaviouralFeature tconv = Type.stringEnumConversionFunctionETL(e1); + res.add(tconv); + } + return res; + } + public void removeInvalidMatchings() - { // remove att -> tatt.f where f is in sources of its owner's attribute matching + { // remove att -> tatt.f where f is in targets of its owner's attribute matching for (int i = 0; i < entitymatches.size(); i++) { EntityMatching em = (EntityMatching) entitymatches.get(i); @@ -224,7 +285,7 @@ public void copySuperclassMatchings(Vector thesaurus, Vector entities) Vector srcsubs = em.realsrc.getSubclasses(); if (srcsup == null && srcsubs.size() > 0) - { em.copyAttributeMappingsToSubclasses(srcsubs,entitymatches,thesaurus,mymap,entities); } + { em.copyAttributeMappingsToSubclasses(srcsubs,entitymatches,thesaurus,this,entities); } } } @@ -292,17 +353,20 @@ else if (Entity.isAncestor(subt,t)) return res; } - public void checkEntityMapCompleteness(Vector targets) + public Vector checkEntityMapCompleteness(Vector targets) { // for every concrete target entity t, warn if no mapping to t or any // superclass of t, if there is a superclass mapping s -> tsup, prompt // for a mapping condition { tcond } s --> t + Vector unused = new Vector(); + for (int i = 0; i < targets.size(); i++) { Entity t = (Entity) targets.get(i); if (t.isConcrete() && t.isTarget()) - { EntityMatching emt = findEntityMatchingByTarget(t,entitymatches); - if (emt == null) - { EntityMatching supemt = findSuperclassMatchingByTarget(t,entitymatches); + { Vector emts = findEntityMatchingsByTarget(t,entitymatches); + if (emts.size() == 0) + { unused.add(t); + EntityMatching supemt = findSuperclassMatchingByTarget(t,entitymatches); if (supemt == null) { System.out.println(">>> Neither " + t + " or any superclass is in the range of the mapping"); @@ -312,10 +376,12 @@ public void checkEntityMapCompleteness(Vector targets) supemt + " is defined."); System.out.println(">>> Suggest conditional mappings { Cond } " + supemt.realsrc + " --> " + t); + // Cond based on unused source features of supemt.realsrc } } } } + return unused; } @@ -331,7 +397,9 @@ public Vector unusedSourceEntities(Vector entities) for (int j = 0; j < entitymatches.size(); j++) { EntityMatching em = (EntityMatching) entitymatches.get(j); if (em.realsrc != null) - { found.add(em.realsrc); } + { found.add(em.realsrc); + found.addAll(em.realsrc.getAllSubclasses()); + } } res.removeAll(found); return res; @@ -341,7 +409,7 @@ public static Vector unusedTargetEntities(Vector entities, Vector ems) { Vector res = new Vector(); for (int i = 0; i < entities.size(); i++) { Entity ex = (Entity) entities.get(i); - if (ex.isTarget()) + if (ex.isTarget() && ex.isConcrete()) { res.add(ex); } } @@ -353,11 +421,15 @@ public static Vector unusedTargetEntities(Vector entities, Vector ems) } res.removeAll(found); return res; - } + } - public Vector analyseCorrelationPatterns(Vector entities) + public Vector unusedTargetEntities(Vector entities) + { return ModelMatching.unusedTargetEntities(entities,entitymatches); } + + public Vector analyseCorrelationPatterns(Vector entities, Vector types) { Vector res = new Vector(); + /* for (int i = 0; i < entities.size(); i++) { Entity e = (Entity) entities.get(i); // some source e /: entitymatches.realsrc @@ -389,30 +461,42 @@ else if (foundtrg == false && e.isTargetEntity()) if (res.contains(p)) { } else { res.add(p); } } - } + } */ for (int i = 0; i < entitymatches.size(); i++) { EntityMatching em = (EntityMatching) entitymatches.get(i); - res.addAll(em.analyseCorrelationPatterns(entitymatches)); + res.addAll(em.analyseCorrelationPatterns(entitymatches,this,entities,types)); } + return res; + } + + + public void addFlagVariables(Vector res) + { + for (int i = 0; i < entitymatches.size(); i++) { EntityMatching em = (EntityMatching) entitymatches.get(i); + + em.removeDuplicateMappings(); + Entity t = em.trg; // The $ form of the entity Vector tvect = new Vector(); tvect.add(t); Vector tsources = mymap.inverseImage(tvect); - if (tsources.size() > 1) + Vector emts = ModelMatching.findEntityMatchingsByTarget(em.realtrg, entitymatches); + if (emts.size() > 1) { System.out.println(">>> Several classes " + tsources + " map to " + t); - + + // if (em.isSpurious(entitymatches)) // { System.out.println(">>> match " + em.realsrc + " |--> " + em.realtrg + // " seems to be spurious, suggest deletion"); // } if (Entity.haveCommonSuperclass(tsources)) - { CorrelationPattern p = new CorrelationPattern("Entity merging (horizontal)", + { CorrelationPattern p = new CorrelationPattern("Class merging (horizontal)", "Entity " + em.realtrg + " is target of " + tsources.size() + " exclusive sources"); p.addTargetEntity(t); @@ -423,6 +507,7 @@ else if (foundtrg == false && e.isTargetEntity()) Entity rtrg = em.realtrg; String flagname = rtrg.getName().toLowerCase() + "Flag"; if (rtrg.hasDefinedAttribute(flagname)) { } + else if (conditionedMatches(emts)) { } else { Attribute tflag = new Attribute(flagname, new Type("String", null), @@ -430,10 +515,9 @@ else if (foundtrg == false && e.isTargetEntity()) tflag.setElementType(new Type("String",null)); rtrg.addAttribute(tflag); - for (int z = 0; z < tsources.size(); z++) - { Entity tsrc = (Entity) tsources.get(z); - EntityMatching emz = ModelMatching.getEntityMatching(tsrc,t,entitymatches); - if (emz != null && emz.realsrc != null) + for (int z = 0; z < emts.size(); z++) + { EntityMatching emz = (EntityMatching) emts.get(z); + if (emz.realsrc != null && emz.realsrc.isConcrete()) { BasicExpression srcvalue = new BasicExpression("\"" + emz.realsrc.getName() + "\""); srcvalue.setType(new Type("String",null)); srcvalue.setElementType(new Type("String",null)); @@ -445,7 +529,7 @@ else if (foundtrg == false && e.isTargetEntity()) } } else - { CorrelationPattern p = new CorrelationPattern("Entity merging (vertical)", + { CorrelationPattern p = new CorrelationPattern("Class merging (vertical)", "Entity " + em.realtrg + " is target of " + tsources.size() + " non-exclusive sources"); p.addTargetEntity(t); @@ -456,14 +540,67 @@ else if (foundtrg == false && e.isTargetEntity()) } // risk of conflict in data, for some feature merges // target should have id attribute, mapped to by id in each source // apart from this and *-mult features, the target features of each mapping - // must be disjoint. + // must be disjoint. Or merge the data if they are not disjoint. } - return res; } + public boolean conditionedMatches(Vector emts) + { // each E --> F in emts has an assignment "F" --> s for some target variable s + + for (int i = 0; i < emts.size(); i++) + { EntityMatching emt = (EntityMatching) emts.get(i); + Entity t = emt.realtrg; + String tname = t.getName(); + if (emt.hasAssignmentOf(tname)) + { return true; } + } + return false; + } + public void removeSpuriousMatchings() - { for (int i = 0; i < entitymatches.size(); i++) + { // E --> F may be spurious if all features of E are already mapped by other entity matchings + // Or, if no mapped feature f uses E as a type/element type + + Vector spurious = new Vector(); + Vector removed = new Vector(); + + for (int i = 0; i < entitymatches.size(); i++) + { EntityMatching em = (EntityMatching) entitymatches.get(i); + Entity s = em.src; // The $ form of the entity + boolean allused = true; // all of s's features are used elsewhere + + Vector satts = s.getAttributes(); + + for (int j = 0; j < satts.size(); j++) + { Attribute f = (Attribute) satts.get(j); + boolean fused = false; + + for (int k = 0; k < entitymatches.size(); k++) + { EntityMatching em2 = (EntityMatching) entitymatches.get(k); + if (i != k && !em.inheritanceRelatedTo(em2)) + { if (em2.usedInSource(f)) + { fused = true; } + } + } + + if (fused == true) { } + else + { allused = false; + break; + } + } + + if (allused) + { System.out.println(">>> match " + em.realsrc + " |--> " + em.realtrg + + " has all source features mapped elsewhere - may be spurious"); + spurious.add(em); + } + } + + + + for (int i = 0; i < entitymatches.size(); i++) { EntityMatching em = (EntityMatching) entitymatches.get(i); Entity t = em.trg; // The $ form of the entity Vector tvect = new Vector(); @@ -473,14 +610,345 @@ public void removeSpuriousMatchings() { System.out.println(">>> Several classes " + tsources + " map to " + t); + if (em.isSpurious(entitymatches)) { System.out.println(">>> match " + em.realsrc + " |--> " + em.realtrg + - " seems to be spurious, suggest deletion"); + " is not used by any feature mappings - may be spurious"); + if (spurious.contains(em)) + { String yn = + JOptionPane.showInputDialog("Remove mapping " + em + + "? (y/n):"); + + if (yn != null && "y".equals(yn)) + { removed.add(em); } + } + } + } + } + entitymatches.removeAll(removed); + // and remove from mymap + for (int i = 0; i < removed.size(); i++) + { EntityMatching rem = (EntityMatching) removed.get(i); + mymap.remove_pair(rem.src, rem.trg); + } + } + + public void checkValidity(Vector unusedtargets, Vector entities, Vector sources, + Vector thesaurus) + { // (i) unused target F1 matches highly with used target F. + // Introduce class splitting: horizontal + // if F, F1 have a common ancestor. + + // (ii) unused mandatory target reference r : R of some F in range of entity matching: + // if (E,R) in entitymatches then add self --> r to the attribute mapping of E -> F, otherwise + // entity split E to R if permitted and add self --> r. + + Vector added = new Vector(); // New entity matches + + for (int i = 0; i < entitymatches.size(); i++) + { EntityMatching em = (EntityMatching) entitymatches.get(i); + Vector unusedmandatorytargets = em.unusedMandatoryTargetReferences(entitymatches); + if (unusedmandatorytargets.size() > 0) + { System.out.println("!! Warning: invalid matching, unused mandatory target features: " + + unusedmandatorytargets + " of " + em.getName()); + + for (int j = 0; j < unusedmandatorytargets.size(); j++) + { Attribute targ = (Attribute) unusedmandatorytargets.get(j); + if (targ.getElementType() != null && targ.getElementType().isEntity()) + { Entity tent = targ.getElementType().getEntity(); + + // Is there already a mapping of em.realsrc to tent? + EntityMatching e2tent = findEntityMatchingFor(em.realsrc,tent,entitymatches); + // or tent is used as intermediate target in em? + boolean usedasintermediate = em.usedAsIntermediateClass(tent); + + if (e2tent == null && !usedasintermediate) + { String yn = + JOptionPane.showInputDialog("Add mapping " + em.realsrc + " |--> " + tent + + "? (y/n):"); + + if (yn != null && "y".equals(yn)) + { String s$ = em.realsrc.getName() + "$"; + String t$ = tent.getName() + "$"; + Entity newsrc = (Entity) ModelElement.lookupByName(s$,entities); + Entity newtrg = (Entity) ModelElement.lookupByName(t$,entities); + EntityMatching newemx = null; + + if (newsrc == null || newtrg == null) + { System.err.println("!! ERROR: no entity " + s$ + " or " + t$); + newemx = new EntityMatching(em.realsrc,tent); + } + else + { newemx = new EntityMatching(newsrc,newtrg,entities); } + // addEntityMatch(newemx,entities); + + added.add(newemx); + unusedtargets.remove(tent); + } + } // But don't do this if tent already occurs as intermediate class in an em.realsrc + // feature mapping target + + String yn = + JOptionPane.showInputDialog("Add feature mapping self |--> " + targ + + "? (y/n):"); + + if (yn != null && "y".equals(yn)) + { BasicExpression selfatt = new BasicExpression(em.realsrc,"self"); + selfatt.setElementType(new Type(em.realsrc)); + Attribute selfvar = new Attribute("self",new Type(em.realsrc), + ModelElement.INTERNAL); + selfvar.setElementType(new Type(em.realsrc)); + AttributeMatching self2mandatory = new AttributeMatching(selfatt,targ); + self2mandatory.setElementVariable(selfvar); + em.addAttributeMatch(self2mandatory); + Vector emsrcsubs = em.realsrc.getSubclasses(); + em.copyAttributeMappingToSubclasses(self2mandatory,emsrcsubs,entitymatches, + thesaurus,this,entities); + + // System.out.println(">> Created new feature map self --> " + targ); + // Also, add it to all subclasses of em.realsrc + } + } } } } + + addEntityMatchings(added,entities); + + for (int h = 0; h < added.size(); h++) + { EntityMatching add = (EntityMatching) added.get(h); + add.src.similarity(add.trg,this,entities,false,false,thesaurus); + Vector srcsubs = add.realsrc.getSubclasses(); + if (srcsubs.size() > 0) + { add.createSubclassMatchings(srcsubs,entitymatches); + add.copyAttributeMappingsToSubclasses(srcsubs,entitymatches,thesaurus,this,entities); + } + } // build feature mappings of the new entity matchings + + + // For unused target entities, look for closest matching source & propose to add + // and to class split. + + + + for (int i = 0; i < unusedtargets.size(); i++) + { Entity ut = (Entity) unusedtargets.get(i); + if (ut.isAbstract()) { continue; } + + double bestscore = 0; + Entity bestmatch = null; + + for (int j = 0; j < sources.size(); j++) + { Entity ej = (Entity) sources.get(j); + String ejname = ej.getName(); + Entity ej$ = (Entity) ModelElement.lookupByName(ejname + "$", entities); + String utname = ut.getName(); + Entity ut$ = (Entity) ModelElement.lookupByName(utname + "$", entities); + double dd = 0; + if (ej$ != null && ut$ != null) + { dd = ej$.similarity(ut$,this,entities,false,false,thesaurus); } + else + { dd = ej.similarity(ut,this,entities,false,false,thesaurus); } + double namesim = ModelElement.similarity(ej.getName().toLowerCase(), + ut.getName().toLowerCase()); + double nmssim = ej.nms$Similarity(ut,thesaurus); + double escore = dd + namesim*ModelMatching.NAMEWEIGHT + + nmssim*ModelMatching.NMSWEIGHT; + System.out.println(">>> Possible match for " + ut + " --> " + ej + " is " + + "NSS=" + namesim + " NMS=" + nmssim + " DSS=" + dd); + + if (escore > bestscore) + { bestscore = escore; + bestmatch = ej; + } + } + + if (bestmatch != null) + { System.out.println(">>> Best match for unused target " + ut + " is " + bestmatch); + String yn = + JOptionPane.showInputDialog("Add class mapping " + bestmatch + " |--> " + ut + + "? (y/n):"); + if (yn != null && "n".equals(yn)) + { sources.remove(bestmatch); + if (sources.size() > 0) + { String othere = + JOptionPane.showInputDialog("Suggest another source from " + + sources + " (name/null)?"); + bestmatch = (Entity) ModelElement.lookupByName(othere,sources); + } + else + { bestmatch = null; } + } + } + + if (bestmatch != null) + { // EntityMatching newem = new EntityMatching(bestmatch,ut); + String s$ = bestmatch.getName() + "$"; + String t$ = ut.getName() + "$"; + Entity newsrc = (Entity) ModelElement.lookupByName(s$,entities); + Entity newtrg = (Entity) ModelElement.lookupByName(t$,entities); + EntityMatching newem = null; + + if (newsrc == null || newtrg == null) + { System.err.println("!! Warning: no entity " + s$ + " or " + t$); + newem = new EntityMatching(bestmatch,ut); + } + else + { newem = new EntityMatching(newsrc,newtrg,entities); } + addEntityMatch(newem,entities); + newem.src.similarity(newem.trg,this,entities,false,false,thesaurus); + // Needs a discriminator if bestmatch now has > 1 target match & no conditions + // look for unused boolean features of bestmatch & test their name similarity to + // ut and other targets. Condition is { bf } bestmatch --> ut if name similarity + // highest for bt, ut names. + + Vector allems = new Vector(); + Vector trgs = isUnconditionalEntitySplitting(bestmatch,allems); + + if (trgs.size() > 1) + { Vector ubools = newem.unusedSourceBooleans(); + Vector ustrings = newem.unusedSourceStrings(); + System.out.println(">>> Unconditional entity splitting of " + + bestmatch + " to: " + trgs); + + if (ubools.size() > 0) + { System.out.println(">>> Unused source boolean features: " + ubools); + for (int p = 0; p < ubools.size(); p++) + { Attribute ub = (Attribute) ubools.get(p); + EntityMatching besttrg = newem; + double besttscore = ModelElement.similarity(ub.getName(), ut.getName()); + for (int k = 0; k < trgs.size(); k++) + { EntityMatching tk = (EntityMatching) trgs.get(k); + double tknss = ModelElement.similarity(ub.getName(), tk.realtrg.getName()); + if (tknss > besttscore) + { besttscore = tknss; + besttrg = tk; + } + } + System.out.println(">>> Best match for " + ub + " is " + besttrg.realtrg); + besttrg.addCondition(new BasicExpression(ub)); + + UnaryExpression negub = new UnaryExpression("not", new BasicExpression(ub)); + + for (int k = 0; k < trgs.size(); k++) + { EntityMatching tk = (EntityMatching) trgs.get(k); + if (tk != besttrg) + { tk.addCondition(negub); } + } + } + } + else if (ustrings.size() > 0) + { System.out.println(">>> Unused source string features: " + ustrings); + Attribute selector = (Attribute) ustrings.get(0); + String yns = + JOptionPane.showInputDialog("Add conditions " + selector + " = target entity name" + + "? (y/n):"); + + if (yns != null && "y".equals(yns)) + { BasicExpression selbe = new BasicExpression(selector); + + for (int k = 0; k < trgs.size(); k++) + { EntityMatching tk = (EntityMatching) trgs.get(k); + BasicExpression tbe = new BasicExpression("\"" + tk.realtrg.getName() + "\""); + tbe.setType(selector.getType()); + tbe.setElementType(selector.getType()); + + BinaryExpression equalstname = new BinaryExpression("=",selbe,tbe); + tk.addCondition(equalstname); + } + } + else + { String ynn = + JOptionPane.showInputDialog("Choose string selector from " + ustrings + + "? (name/null):"); + + if (ynn != null && !"null".equals(ynn)) + { Attribute selsel = (Attribute) ModelElement.lookupByName(ynn,ustrings); + if (selsel != null) + { BasicExpression selbe = new BasicExpression(selsel); + + for (int k = 0; k < trgs.size(); k++) + { EntityMatching tk = (EntityMatching) trgs.get(k); + BasicExpression tbe = new BasicExpression("\"" + tk.realtrg.getName() + "\""); + tbe.setType(selsel.getType()); + tbe.setElementType(selsel.getType()); + BinaryExpression equalstname = new BinaryExpression("=",selbe,tbe); + tk.addCondition(equalstname); + } + } + } + } + } + else + { Vector featuresets = new Vector(); + Vector otherconds = newem.unusedSourceConditions(featuresets); + + Vector matchedconditions = new Vector(); + Vector matchedtargets = new Vector(); + + System.out.println(">>> Possible discriminator conditions are: " + otherconds); + for (int k = 0; k < trgs.size(); k++) + { EntityMatching tk = (EntityMatching) trgs.get(k); + if (matchedtargets.contains(tk.realtrg)) { } + else + { Expression bestcond = null; + Vector bestconds = new Vector(); + + double besttscore = 0; + + for (int p = 0; p < featuresets.size(); p++) + { Attribute ub = (Attribute) featuresets.get(p); + Expression newcond = (Expression) otherconds.get(p); + if (matchedconditions.contains(newcond + "")) { } + else + { double tknss = // ModelElement.similarity(ub.getName(), tk.realtrg.getName()); + Entity.nmsSimilarity(ub.getName(), tk.realtrg.getName(), thesaurus); + System.out.println(">>> NMS similarity of " + ub + " and " + tk.realtrg + + " = " + tknss); + + if (tknss > besttscore) + { besttscore = tknss; + bestcond = newcond; + bestconds.clear(); + bestconds.add(newcond); + } + else if (tknss == besttscore) + { bestconds.add(newcond); } + } + } + if (besttscore > 0) + { + System.out.println(">>> Best matches for " + tk.realtrg + " are " + bestconds); + tk.addCondition(bestcond); + // add negation of bestcond to the other ones + + matchedconditions.add(bestcond + ""); + matchedtargets.add(tk.realtrg); + } + else + { System.out.println(">>> No discriminator available for " + tk.realtrg); } + } + } + } + } + } + } + + } + + public void checkTargetFeatureCompleteness(Vector entities, Vector sources, + Vector thesaurus) + { // are all target features used in the target of some entitymatch? + // if not, search for similar targets that are used, or similar sources. + + for (int i = 0; i < entitymatches.size(); i++) + { EntityMatching em = (EntityMatching) entitymatches.get(i); + em.checkTargetFeatureCompleteness(entitymatches,thesaurus); + } } + + public int size() { return mymap.size(); } @@ -489,13 +957,17 @@ public double nameSimilarity() for (int i = 0; i < entitymatches.size(); i++) { EntityMatching em = (EntityMatching) entitymatches.get(i); Entity s = em.src; + if (em.realsrc != null) + { s = em.realsrc; } Entity t = em.trg; + if (em.realtrg != null) + { t = em.realtrg; } double sim = ModelElement.similarity(s.getName().toLowerCase(), t.getName().toLowerCase()); res = res + sim; } return res; - } + } // better to use realsrc. public double graphSimilarity(Map srcgraph, Map trggraph, Map mm1, Vector entities) { double res = 0; @@ -603,6 +1075,28 @@ public void setRealAttributeMatches(Entity source, Entity target, Vector srcatts } } + + public Vector isUnconditionalEntitySplitting(Entity src, Vector alltargets) + { Vector targets = new Vector(); + + for (int i = 0; i < entitymatches.size(); i++) + { EntityMatching em = (EntityMatching) entitymatches.get(i); + if (src == em.realsrc) + { alltargets.add(em); + + if (em.getCondition() == null) + { targets.add(em); } + else if ("true".equals(em.getCondition() + "")) + { targets.add(em); } + } + } + + if (targets.size() > 0 && targets.size() == alltargets.size()) + { System.out.println(">>> All mappings from " + src + " are unconditioned."); } + + return targets; + } + public String qvtTransformation(Vector econvs, Vector seconvs, Vector esconvs, Vector benums, Vector ebools) { String res = "transformation tau(source: MM1, target: MM2)\n" + @@ -647,13 +1141,64 @@ public String qvtTransformation(Vector econvs, Vector seconvs, Vector esconvs, for (int i = 0; i < entitymatches.size(); i++) { EntityMatching em = (EntityMatching) entitymatches.get(i); - if (em.isConcrete()) + if (em.isConcrete() && em.isConcreteTarget()) { res = res + em.qvtrule2(entitymatches) + "\n"; } } // omits mapping to primary keys of em.realtarget return res + "\n}\n"; } + public String qvtBxTransformation(Vector econvs, Vector seconvs, Vector esconvs, + Vector benums, Vector ebools) + { String res = "transformation tau(source: MM1, target: MM2)\n" + + "{ \n"; + + for (int i = 0; i < econvs.size(); i++) + { Maplet mt = (Maplet) econvs.get(i); + Type t1 = (Type) mt.source; + Type t2 = (Type) mt.dest; + if (t1.isEnumeration() && t2.isEnumeration()) + { res = res + " " + Type.enumConversionOpQVT(t1,t2) + "\n\n" + Type.enumConversionOpQVT(t2,t1) + "\n\n"; } + } + + for (int i = 0; i < seconvs.size(); i++) + { Type et = (Type) seconvs.get(i); + if (et.isEnumeration()) + { res = res + " " + et.stringEnumQueryOpQVTR() + "\n\n" + et.enumStringQueryOpQVTR() + "\n\n"; } + } // Only include functions that are actually used + + for (int i = 0; i < esconvs.size(); i++) + { Type et = (Type) esconvs.get(i); + if (et.isEnumeration()) + { res = res + " " + et.enumStringQueryOpQVTR() + "\n\n" + et.stringEnumQueryOpQVTR() + "\n\n"; } + } + + for (int i = 0; i < benums.size(); i++) + { Type et = (Type) benums.get(i); + if (et.isEnumeration()) + { res = res + " " + Type.booleanEnumOpQVTR(et) + "\n\n" + Type.enumBooleanOpQVTR(et) + "\n\n"; } + } + + for (int i = 0; i < ebools.size(); i++) + { Type et = (Type) ebools.get(i); + if (et.isEnumeration()) + { res = res + " " + Type.enumBooleanOpQVTR(et) + "\n\n" + Type.booleanEnumOpQVTR(et); } + } + + for (int i = 0; i < entitymatches.size(); i++) + { EntityMatching em = (EntityMatching) entitymatches.get(i); + res = res + em.qvtrule1bx(entitymatches) + "\n"; + } // must include mapping to any primary key of em.realtarget + + for (int i = 0; i < entitymatches.size(); i++) + { EntityMatching em = (EntityMatching) entitymatches.get(i); + if (em.isConcrete() && em.isConcreteTarget()) + { res = res + em.qvtrule2bx(entitymatches) + "\n"; } + } + + return res + "\n}\n"; + } + public String umlrsdsTransformation(Vector econvs, Vector esconvs, Vector seconvs, Vector beconvs, Vector ebconvs) { String res = " usecase app {\n"; @@ -698,7 +1243,7 @@ public String umlrsdsTransformation(Vector econvs, Vector esconvs, Vector seconv for (int i = 0; i < entitymatches.size(); i++) { EntityMatching em = (EntityMatching) entitymatches.get(i); - if (em.isConcrete()) + if (em.isConcrete() && em.isConcreteTarget()) { res = res + em.umlrsdsrule2(entitymatches) + "\n"; } } @@ -707,7 +1252,9 @@ public String umlrsdsTransformation(Vector econvs, Vector esconvs, Vector seconv public String qvtoTransformation(Vector econvs, Vector esconvs, Vector seconvs, Vector benums, Vector ebools, Vector thesaurus) - { String res = "transformation tau(in : src, out : trg);\n\n"; + { String res = "modeltype MM1 uses 'http://mm1.com/';\n" + + "modeltype MM2 uses 'http://mm2.com/';\n\n\n" + + "transformation tau(in src : MM1, out trg : MM2);\n\n"; for (int i = 0; i < econvs.size(); i++) { Maplet mt = (Maplet) econvs.get(i); @@ -751,7 +1298,7 @@ public String qvtoTransformation(Vector econvs, Vector esconvs, Vector seconvs, for (int i = 0; i < entitymatches.size(); i++) { EntityMatching em = (EntityMatching) entitymatches.get(i); - if (em.isConcrete()) + if (em.isConcrete() && em.isConcreteTarget()) { res = res + em.qvtomain2() + "\n"; } } @@ -767,7 +1314,7 @@ public String qvtoTransformation(Vector econvs, Vector esconvs, Vector seconvs, for (int i = 0; i < entitymatches.size(); i++) { EntityMatching em = (EntityMatching) entitymatches.get(i); - if (em.isConcrete()) + if (em.isConcrete() && em.isConcreteTarget()) { res = res + em.qvtorule2(entitymatches) + "\n"; } } @@ -777,22 +1324,89 @@ public String qvtoTransformation(Vector econvs, Vector esconvs, Vector seconvs, public String atlTransformation(Vector types) { String res = ""; - /* for (int i = 0; i < types.size(); i++) - { Type et = (Type) types.get(i); - if (et.isEnumeration()) - { res = res + " " + et.enumQueryOpsATL() + "\n\n"; } - } */ + java.util.Map fromCommonSource = new java.util.HashMap(); + // entity name --> Vector of mappings with same entity for (int i = 0; i < entitymatches.size(); i++) { EntityMatching em = (EntityMatching) entitymatches.get(i); - if (em.isConcrete()) - { res = res + em.atlrule(entitymatches) + "\n"; } + if (em.isConcrete() && em.isConcreteTarget()) + { Entity emsrc = em.realsrc; + String key = emsrc.getName() + "{" + em.getCondition() + "}"; + Vector emsrcmappings = (Vector) fromCommonSource.get(key); + if (emsrcmappings == null) + { emsrcmappings = new Vector(); + em.isSecondary = false; + } + else + { em.isSecondary = true; + EntityMatching r1 = (EntityMatching) emsrcmappings.get(0); + em.isSecondaryTo = r1.getName(); + } + emsrcmappings.add(em); + fromCommonSource.put(key,emsrcmappings); + } + } + + System.out.println(">> ATL rule groups: " + fromCommonSource); + + for (int i = 0; i < entitymatches.size(); i++) + { EntityMatching em = (EntityMatching) entitymatches.get(i); + if (em.isConcrete() && em.isConcreteTarget() && em.isPrimary()) + { Vector secondaryRules = new Vector(); + String rkey = em.realsrc.getName() + "{" + em.getCondition() + "}"; + secondaryRules.addAll((Vector) fromCommonSource.get(rkey)); + secondaryRules.remove(em); + res = res + em.atlrule(entitymatches,secondaryRules) + "\n"; + } } return res + "\n\n"; } + public EtlModule etlTransformation(Vector types, Vector benums, Vector benames, + Vector ebools, Vector ebnames) + { EtlModule res = new EtlModule("Autogenerated"); + + for (int i = 0; i < benums.size(); i++) + { Type et = (Type) benums.get(i); + String trgname = (String) benames.get(i); + if (et.isEnumeration()) + { BehaviouralFeature bf = + Type.booleanEnumConversionFunctionETL(et,trgname); + if (bf != null) + { res.addOperation(bf); } + } + } // Only include functions that are actually used + + for (int i = 0; i < ebools.size(); i++) + { Type et = (Type) ebools.get(i); + String trgnme = (String) ebnames.get(i); + if (et.isEnumeration()) + { BehaviouralFeature bf = Type.enumBooleanConversionFunctionETL(et,trgnme); + if (bf != null) + { res.addOperation(bf); } + } + } // Only include functions that are actually used + + Vector auxrules = new Vector(); + + for (int i = 0; i < entitymatches.size(); i++) + { EntityMatching em = (EntityMatching) entitymatches.get(i); + // if (em.isConcrete()) + res.addRule(em.etlrule(entitymatches,auxrules)); + } + + for (int y = 0; y < auxrules.size(); y++) + { Object arx = auxrules.get(y); + if (arx instanceof TransformationRule) + { res.addRule((TransformationRule) arx); } + else if (arx instanceof BehaviouralFeature) + { res.addOperation((BehaviouralFeature) arx); } + } + return res; + } + public static Entity lookupMatch(Entity s, Vector ems) { for (int i = 0; i < ems.size(); i++) { EntityMatching em = (EntityMatching) ems.get(i); @@ -816,6 +1430,18 @@ else if (em.src != null && em.src.getName().equals(s.getName())) return null; } + public static Vector getMatchings(Entity s, Vector ems) + { Vector res = new Vector(); + for (int i = 0; i < ems.size(); i++) + { EntityMatching em = (EntityMatching) ems.get(i); + if (em.src == s) + { res.add(em); } + else if (em.src != null && em.src.getName().equals(s.getName())) + { res.add(em); } + } + return res; + } + public EntityMatching getMatching(Entity s) { return getMatching(s,entitymatches); } @@ -829,6 +1455,17 @@ public static Entity lookupRealMatch(Entity s, Vector ems) return null; } + public static Vector lookupRealMatches(Entity s, Vector ems) + { Vector res = new Vector(); + + for (int i = 0; i < ems.size(); i++) + { EntityMatching em = (EntityMatching) ems.get(i); + if (em.realsrc == s) + { res.add(em.realtrg); } + } + return res; + } + public static EntityMatching findEntityMatching(Entity s, Vector ems) { // some matching that can map elements of type s. @@ -844,6 +1481,40 @@ public static EntityMatching findEntityMatching(Entity s, Vector ems) return null; } + public static Vector findEntityMatchings(Entity s, Vector ems) + { // closest matchings that can map elements of type s. + Vector res = new Vector(); + + for (int i = 0; i < ems.size(); i++) + { EntityMatching em = (EntityMatching) ems.get(i); + if (em.realsrc == s) + { res.add(em); } + else + { Entity srcsup = s.getSuperclass(); + if (srcsup != null) + { res.addAll(ModelMatching.findEntityMatchings(srcsup,ems)); } + } + } + return null; + } + + public static EntityMatching findEntityMatchingFor(Entity s, Entity t, Vector ems) + { // some matching that can map elements of type s to type t. + if (s == null || t == null) + { return null; } + + for (int i = 0; i < ems.size(); i++) + { EntityMatching em = (EntityMatching) ems.get(i); + if (em.realsrc == s && Entity.isDescendant(em.realtrg,t)) + { return em; } + } + + Entity srcsup = s.getSuperclass(); + if (srcsup != null) + { return ModelMatching.findEntityMatchingFor(srcsup,t,ems); } + return null; + } + public static EntityMatching findEntityMatchingByTarget(Entity t, Vector ems) { // some matching that can map elements to type t. @@ -856,6 +1527,20 @@ public static EntityMatching findEntityMatchingByTarget(Entity t, Vector ems) return null; } + public static Vector findEntityMatchingsByTarget(Entity t, Vector ems) + { // all matchings that can map elements to type t. + + Vector res = new Vector(); + + for (int i = 0; i < ems.size(); i++) + { EntityMatching em = (EntityMatching) ems.get(i); + if (em.realtrg == t) + { res.add(em); } + } + + return res; + } + public static EntityMatching findSuperclassMatchingByTarget(Entity t, Vector ems) { // some matching that can map elements to type t. @@ -871,6 +1556,41 @@ public static EntityMatching findSuperclassMatchingByTarget(Entity t, Vector ems return null; } + public static EntityMatching findSuperclassMatchingBySourceTarget(Entity s, Entity t, Vector ems) + { // some matching with s descendant of realsrc, t of realtrg + + for (int i = 0; i < ems.size(); i++) + { EntityMatching em = (EntityMatching) ems.get(i); + if (em.realsrc == s && Entity.isDescendant(t,em.realtrg)) + { return em; } + } + + Entity srcsup = s.getSuperclass(); + if (srcsup != null) + { return ModelMatching.findSuperclassMatchingBySourceTarget(srcsup,t,ems); } + return null; + } + + public static Vector findSpecialisedMatchingsBySourceTarget(Entity s, Entity t, Vector ems) + { // all matchings with t = or descendant of realtrg + Vector res = new Vector(); + + for (int i = 0; i < ems.size(); i++) + { EntityMatching em = (EntityMatching) ems.get(i); + if (em.realsrc == s && Entity.isDescendant(t,em.realtrg)) + { res.add(em); } + } + + if (res.size() == 0) + { Vector srcsubs = s.getSubclasses(); + for (int j = 0; j < srcsubs.size(); j++) + { Entity srcsub = (Entity) srcsubs.get(j); + res.addAll(findSpecialisedMatchingsBySourceTarget(srcsub,t,ems)); + } + } + return res; + } + public static EntityMatching getEntityMatching(Entity s, Vector ems) { // the exact matching that maps elements of type s. @@ -883,6 +1603,19 @@ public static EntityMatching getEntityMatching(Entity s, Vector ems) return null; } + public static Vector getEntityMatchings(Entity s, Vector ems) + { // all matchings that map elements of type s. + Vector res = new Vector(); + + for (int i = 0; i < ems.size(); i++) + { EntityMatching em = (EntityMatching) ems.get(i); + if (em.realsrc == s) + { res.add(em); } + } + + return res; + } + public static EntityMatching getEntityMatching(Entity s, Entity t, Vector ems) { // the exact matching that maps elements of type s to t. @@ -907,6 +1640,23 @@ public static EntityMatching getRealEntityMatching(Entity s, Entity t, Vector em return null; } + public static EntityMatching getAncestorMatching(Entity srcsup, Entity realtrg, Vector ems) + { for (int i = 0; i < ems.size(); i++) + { EntityMatching em = (EntityMatching) ems.get(i); + if (em.realsrc == srcsup && + (realtrg == em.realtrg || + Entity.isDescendant(realtrg,em.realtrg)) + ) + { return em; } + else if (srcsup.getSuperclass() != null) + { EntityMatching emx = getAncestorMatching(srcsup.getSuperclass(), realtrg, ems); + if (emx != null) + { return emx; } + } + } + return null; + } + public EntityMatching getEntityMatching(Entity s) { return getEntityMatching(s,entitymatches); } @@ -917,6 +1667,16 @@ public Vector getAttributeMapping(Entity ent) return null; } + public static boolean isUnusedTargetByName(Attribute att, Vector ems) + { for (int i = 0; i < ems.size(); i++) + { EntityMatching em = (EntityMatching) ems.get(i); + if (em.isUnusedTargetByName(att)) { } + else + { return false; } + } + return true; + } + public static boolean isUnusedTarget(Attribute att, Vector ems) { for (int i = 0; i < ems.size(); i++) { EntityMatching em = (EntityMatching) ems.get(i); @@ -937,11 +1697,14 @@ public static boolean compatibleType(Attribute satt, Attribute tatt, Vector ems) { Entity e1 = setype.getEntity(); Entity e2 = tetype.getEntity(); // and e1 maps to e2 or a subclass of it - Entity e1img = ModelMatching.lookupRealMatch(e1,ems); - if (e1img == e2) - { return true; } - if (Entity.isAncestor(e2,e1img)) - { return true; } + Vector e1imgs = ModelMatching.lookupRealMatches(e1,ems); + for (int i = 0; i < e1imgs.size(); i++) + { Entity e1img = (Entity) e1imgs.get(i); + if (e1img == e2) + { return true; } + if (Entity.isAncestor(e2,e1img)) + { return true; } + } } else if ((setype + "").equals(tetype + "")) { return true; } @@ -957,11 +1720,14 @@ public static boolean compatibleReverse(Attribute satt, Attribute tatt, Vector e setype.isEntity()) { Entity e1 = setype.getEntity(); // and e1 maps to e2 or a subclass of it - Entity e1img = ModelMatching.lookupRealMatch(e1,ems); - if (e1img == e2) - { return true; } - if (Entity.isAncestor(e2,e1img)) - { return true; } + Vector e1imgs = ModelMatching.lookupRealMatches(e1,ems); + for (int i = 0; i < e1imgs.size(); i++) + { Entity e1img = (Entity) e1imgs.get(i); + if (e1img == e2) + { return true; } + if (Entity.isAncestor(e2,e1img)) + { return true; } + } } return false; } @@ -976,10 +1742,9 @@ public static Expression defineCombinedExpression(Attribute unused, Attribute us Expression unusedExp = new BasicExpression(unused); unusedExp.setUmlKind(Expression.ATTRIBUTE); - if (used.isDirect() && - unused.isDirect() && + if (used.isDirect() && "String".equals(targetType.getName())) - { BasicExpression sep = new BasicExpression("\"~\""); + { BasicExpression sep = new BasicExpression("\" ~ \""); sep.setType(new Type("String", null)); sep.setElementType(new Type("String", null)); Expression res = @@ -1280,6 +2045,65 @@ public static Expression defineCombinedExpression(Vector sametargets, return r; } + + public static AttributeMatching defineFeatureSplitting(AttributeMatching am, Attribute newtrg) + { Attribute src = am.src; + Attribute oldtrg = am.trg; + + Type srctype = src.getType(); + Type trgtype = oldtrg.getType(); + Type newtype = newtrg.getType(); + + Expression srcExp = new BasicExpression(src); + srcExp.setUmlKind(Expression.ATTRIBUTE); + Expression newExp = new BasicExpression(newtrg); + newExp.setUmlKind(Expression.ATTRIBUTE); + + if ("String".equals(srctype.getName()) && "String".equals(trgtype.getName()) && + "String".equals(newtype.getName())) + { BasicExpression sep = new BasicExpression("\" ~ \""); + sep.setType(new Type("String", null)); + sep.setElementType(new Type("String", null)); + Expression src1 = + new BinaryExpression("->before", srcExp, sep); + src1.setType(new Type("String", null)); + src1.setElementType(new Type("String", null)); + src1.setMultiplicity(ModelElement.ONE); + Expression src2 = + new BinaryExpression("->after", srcExp, sep); + src2.setType(new Type("String", null)); + src2.setElementType(new Type("String", null)); + src2.setMultiplicity(ModelElement.ONE); + // am.srcvalue = src1; + // am.elementVariable = src; + Attribute var1 = new Attribute(Identifier.nextIdentifier("var$"),srctype, + ModelElement.INTERNAL); + var1.setElementType(srctype); + am.setExpressionMatch(src1,am.trg,var1); + Attribute var2 = new Attribute(Identifier.nextIdentifier("var$"),srctype, + ModelElement.INTERNAL); + var2.setElementType(srctype); + Vector auxvariables = new Vector(); + // auxvariables.add(var1); + auxvariables.add(var2); + AttributeMatching res = new AttributeMatching(src2,newtrg,var2,auxvariables); + + return res; + } + return null; + } + + public void checkModel(ModelSpecification mod) + { // For each feature mapping f |--> g, checks for each + // ex : E and corresponding fx : F, that ex.f = fx.g in + // the model. + + for (int i = 0; i < entitymatches.size(); i++) + { EntityMatching em = (EntityMatching) entitymatches.get(i); + em.checkModel(mod); + } + } + } diff --git a/ModelSpecification.java b/ModelSpecification.java new file mode 100644 index 00000000..d8c7efc3 --- /dev/null +++ b/ModelSpecification.java @@ -0,0 +1,206 @@ +import java.util.*; +import java.io.*; + +/****************************** +* Copyright (c) 2003,2019 Kevin Lano +* This program and the accompanying materials are made available under the +* terms of the Eclipse Public License 2.0 which is available at +* http://www.eclipse.org/legal/epl-2.0 +* +* SPDX-License-Identifier: EPL-2.0 +* *****************************/ + +public class ModelSpecification +{ Vector objects = new Vector(); + java.util.Map objectmap = new java.util.HashMap(); + java.util.Map objectsOfClass = new java.util.HashMap(); + + public void addObject(ObjectSpecification obj) + { objects.add(obj); + objectmap.put(obj.getName(),obj); + if (obj.entity != null) + { Entity ent = obj.entity; + Vector res = (Vector) objectsOfClass.get(ent.getName()); + if (res == null) + { res = new Vector(); } + res.add(obj); + objectsOfClass.put(ent.getName(),res); + } + } + + + public String toString() + { String res = "MODEL "; + for (int i = 0; i < objects.size(); i++) + { res = res + objects.get(i) + "\n"; } + return res; + } + + public ObjectSpecification getObject(String nme) + { return (ObjectSpecification) objectmap.get(nme); } + + public ObjectSpecification getCorrespondingObject(String sename, String tename, String nme) + { Vector sobjs = getObjects(sename); + Vector tobjs = getObjects(tename); + ObjectSpecification sobj = getObject(nme); + if (sobj == null) + { return null; } + + int sind = sobjs.indexOf(sobj); + if (sind < tobjs.size()) + { return (ObjectSpecification) tobjs.get(sind); } + return null; + } + + public ObjectSpecification getCorrespondingObject(String sename, String tename, ObjectSpecification sobj) + { Vector sobjs = getObjects(sename); + Vector tobjs = getObjects(tename); + + if (sobj == null) + { return null; } + + int sind = sobjs.indexOf(sobj); + if (sind < tobjs.size()) + { return (ObjectSpecification) tobjs.get(sind); } + return null; + } + + public ObjectSpecification getSourceObject(String sename, String tename, String nme) + { Vector sobjs = getObjects(sename); + Vector tobjs = getObjects(tename); + ObjectSpecification tobj = getObject(nme); + if (tobj == null) + { return null; } + + int tind = tobjs.indexOf(tobj); + if (tind < sobjs.size()) + { return (ObjectSpecification) sobjs.get(tind); } + return null; + } + + public ObjectSpecification getSourceObject(String sename, String tename, ObjectSpecification tobj) + { Vector sobjs = getObjects(sename); + Vector tobjs = getObjects(tename); + + if (tobj == null) + { return null; } + + int tind = tobjs.indexOf(tobj); + if (tind < sobjs.size()) + { return (ObjectSpecification) sobjs.get(tind); } + return null; + } + + public Vector getObjects(String ename) + { Vector res = (Vector) objectsOfClass.get(ename); + if (res == null) + { return new Vector(); } + return res; + } + + public Vector getCorrespondingObjects(String sename, String tename, Collection sobjs) + { Vector res = new Vector(); + + for (Object x : sobjs) + { ObjectSpecification sobj = (ObjectSpecification) x; + ObjectSpecification tobj = getCorrespondingObject(sename, tename, sobj); + if (tobj != null) + { res.add(tobj); } + } + return res; + } + + public Vector getSourceObjects(String sename, String tename, Collection tobjs) + { Vector res = new Vector(); + + for (Object x : tobjs) + { ObjectSpecification tobj = (ObjectSpecification) x; + ObjectSpecification sobj = getSourceObject(sename, tename, tobj); + if (sobj != null) + { res.add(sobj); } + } + return res; + } + + + public boolean correspondingObjects(String sename, String tename, ObjectSpecification sobj, ObjectSpecification tobj) + { Vector sobjs = getObjects(sename); + Vector tobjs = getObjects(tename); + int ind1 = sobjs.indexOf(sobj); + int ind2 = tobjs.indexOf(tobj); + if (ind1 >= 0 && ind2 >= 0 && ind1 == ind2) + { return true; } + return false; + } + + public boolean correspondingObjectSequences(String sename, String tename, Vector svals, Vector tvals) + { if (svals.size() != tvals.size()) + { return false; } + + Vector sobjs = getObjects(sename); + Vector tobjs = getObjects(tename); + for (int i = 0; i < svals.size(); i++) + { ObjectSpecification sobj = (ObjectSpecification) svals.get(i); + ObjectSpecification tobj = (ObjectSpecification) tvals.get(i); + if (sobjs.indexOf(sobj) >= 0 && + sobjs.indexOf(sobj) == tobjs.indexOf(tobj)) + { } + else + { return false; } + } + return true; + } + + public boolean correspondingObjectSets(String sename, String tename, Vector svals, Vector tvals) + { + Vector sobjs = getObjects(sename); + Vector tobjs = getObjects(tename); + + for (int i = 0; i < svals.size(); i++) + { ObjectSpecification sobj = (ObjectSpecification) svals.get(i); + ObjectSpecification tobj = getCorrespondingObject(sename,tename,sobj.getName()); + System.out.println(">>> Corresponding object of " + sobj.getName() + " is " + tobj); + + if (tobj != null && tvals.contains(tobj)) + { } + else + { return false; } + } + + for (int i = 0; i < tvals.size(); i++) + { ObjectSpecification tobj = (ObjectSpecification) tvals.get(i); + ObjectSpecification sobj = getCorrespondingObject(tename,sename,tobj.getName()); + System.out.println(">>> Corresponding object of " + tobj.getName() + " is " + sobj); + + if (sobj != null && svals.contains(sobj)) + { } + else + { return false; } + } + + return true; + } + + public Vector correspondingObjectSubset(String sename, + String tename, Vector svals, Vector tvals) + { // For each source element there is a corresponding target + + Vector sobjs = getObjects(sename); + Vector tobjs = getObjects(tename); + Vector res = new Vector(); + + for (int i = 0; i < svals.size(); i++) + { ObjectSpecification sobj = (ObjectSpecification) svals.get(i); + ObjectSpecification tobj = getCorrespondingObject(sename,tename,sobj.getName()); + // System.out.println(">>> Corresponding object of " + sobj.getName() + " is " + tobj); + + if (tobj != null && tvals.contains(tobj)) + { res.add(tobj); } + else + { return null; } + } + return res; + } + + +} diff --git a/ObjectSpecification.java b/ObjectSpecification.java index 1368e813..cbe64648 100644 --- a/ObjectSpecification.java +++ b/ObjectSpecification.java @@ -13,10 +13,10 @@ public class ObjectSpecification extends ModelElement { // String objectName; - String objectClass; - Entity entity; + String objectClass = ""; + Entity entity = null; List atts = new ArrayList(); // String - java.util.Map attvalues = new HashMap(); // String --> String + java.util.Map attvalues = new HashMap(); // String --> Object List elements = new ArrayList(); // ObjectSpecification boolean isSwingObject = true; @@ -30,11 +30,85 @@ public ObjectSpecification(String nme, String typ) { isSwingObject = false; } } + public void setEntity(Entity cls) + { entity = cls; } + public String toString() - { return getName() + " : " + objectClass + "\n" + - attvalues + "\n" + elements +"\n\n"; + { return getName() + " : " + objectClass + " { " + + attvalues + "; " + elements + " }"; } + public boolean equals(Object x) + { if (x instanceof ObjectSpecification) + { ObjectSpecification spec = (ObjectSpecification) x; + String xname = spec.getName(); + return xname.equals(getName()) && + spec.attvalues != null && attvalues != null && + attvalues.equals(spec.attvalues); + } + return false; + } + + + public int getInt(String att) + { // Where we know that att represents an int value + String val = (String) attvalues.get(att); + if (val != null) + { int x = Integer.parseInt(val); + return x; + } + return 0; + } + + public long getLong(String att) + { // Where we know that att represents an int value + String val = (String) attvalues.get(att); + if (val != null) + { long x = Long.parseLong(val); + return x; + } + return 0; + } + + public double getDouble(String att) + { // Where we know that att represents an int value + String val = (String) attvalues.get(att); + if (val != null) + { double x = Double.parseDouble(val); + return x; + } + return 0; + } + + public double getNumeric(String att) + { double res = 0; + + String val = (String) attvalues.get(att); + if (val != null) + { try { res = Integer.parseInt(val); } + catch (Exception _e) + { try { res = Long.parseLong(val); } + catch (Exception _f) + { res = Double.parseDouble(val); } + } + } + return res; + } + + public String getString(String att) + { + String val = (String) attvalues.get(att); + return val.substring(1,val.length()-1); + } // Need also to remove the quotes + + public Vector getCollection(String att) + { Vector res = (Vector) attvalues.get(att); + if (res == null) + { return new Vector(); } + return res; + } + + public static boolean isJavaGUIClass(String s) { return s.equals("Frame") || s.equals("Panel") || s.equals("Button") || s.equals("MenuBar") || s.equals("Menu") || s.equals("MenuItem") || @@ -43,10 +117,41 @@ public static boolean isJavaGUIClass(String s) } public void addAttribute(String att, String value) - { atts.add(att); + { if (atts.contains(att)) { } + else + { atts.add(att); } + attvalues.put(att,value); + } + + public void addAttribute(String att, Vector value) + { if (atts.contains(att)) { } + else + { atts.add(att); } attvalues.put(att,value); } + public void addAttributeElement(String att, String value) + { Vector v = new Vector(); + if (atts.contains(att)) + { v = (Vector) attvalues.get(att); } + else + { atts.add(att); + attvalues.put(att,v); + } + v.add(value); + } + + public void addAttributeElement(String att, ObjectSpecification value) + { Vector v = new Vector(); + if (atts.contains(att)) + { v = (Vector) attvalues.get(att); } + else + { atts.add(att); + attvalues.put(att,v); + } + v.add(value); + } + public void addelement(ObjectSpecification elem) { elements.add(elem); } diff --git a/ObjectTemplateExp.java b/ObjectTemplateExp.java index 8a2fecf9..beb44d9c 100644 --- a/ObjectTemplateExp.java +++ b/ObjectTemplateExp.java @@ -13,6 +13,7 @@ public class ObjectTemplateExp extends TemplateExp { Entity referredClass; Vector part = new Vector(); // PropertyTemplateItem + boolean leastchange = false; public ObjectTemplateExp(Attribute att, Expression ex, Entity e) { super(att,ex); @@ -24,6 +25,9 @@ public ObjectTemplateExp(Attribute att, Entity e) referredClass = e; } + public void setLeastChange(boolean lc) + { leastchange = lc; } + public Object clone() { Expression wclone = null; if (where != null) @@ -33,6 +37,7 @@ public Object clone() { PropertyTemplateItem pti = (PropertyTemplateItem) part.get(i); res.addpart((PropertyTemplateItem) pti.clone()); } + res.leastchange = leastchange; return res; } @@ -212,13 +217,14 @@ public boolean typeCheck(Vector types, Vector entities, Vector contexts, Vector return true; } - public Expression toGuardCondition(Vector bound, Expression contextObj, Expression post) + public Expression toGuardCondition(Vector bound, Expression contextObj, Expression post, + Entity tr) { Expression res = new BasicExpression(true); String bind = bindsTo.getName(); boolean alreadybound = bound.contains(bind); - System.out.println("BOUND = " + bound + " BINDS TO= " + bindsTo); + // System.out.println("BOUND = " + bound + " BINDS TO= " + bindsTo); res = Expression.simplify("&",where,post,null); @@ -228,7 +234,10 @@ public Expression toGuardCondition(Vector bound, Expression contextObj, Expressi res = p.toGuardCondition(bound, contextObj, res); } - Expression btexp = new BasicExpression(bindsTo); + BasicExpression btexp = new BasicExpression(bindsTo); + btexp.setUmlKind(Expression.ROLE); + btexp.setEntity(tr); + // Expression scope = new BasicExpression(referredClass); // Expression decl = new BinaryExpression(":", btexp, scope); // res = Expression.simplify("&",decl,res,null); @@ -259,7 +268,8 @@ public Expression toSourceExpression(Vector bound, Expression contextObj) res = Expression.simplify("&",res,pexp,null); } - res = Expression.simplify("&",res,where,null); + Expression fwhere = filterWhereSource(bound,where); + res = Expression.simplify("&",res,fwhere,null); // Expression btexp = new BasicExpression(bindsTo); // Expression scope = new BasicExpression(referredClass); // Expression decl = new BinaryExpression(":", btexp, scope); @@ -267,6 +277,56 @@ public Expression toSourceExpression(Vector bound, Expression contextObj) return res; } + private Expression filterWhereSource(Vector bound,Expression expr) + { if (expr == null) + { return null; } + + // bindsTo.f = e only permitted if variables of e are subset of bound. + // Likewise for e : bindsTo.f, etc + + if (expr instanceof BinaryExpression) + { BinaryExpression be = (BinaryExpression) expr; + if (be.getOperator().equals("&")) + { Expression eleft = filterWhereSource(bound, be.getLeft()); + Expression eright = filterWhereSource(bound, be.getRight()); + return Expression.simplify("&", eleft, eright,null); + } + else if (be.getOperator().equals("!")) + { BinaryExpression eleft = (BinaryExpression) be.getLeft(); + Vector newbound = new Vector(); + newbound.add(eleft.getLeft() + ""); + newbound.addAll(bound); + Expression fleft = filterWhereSource(bound, eleft); + Expression eright = be.getRight(); + Expression fright = filterWhereSource(newbound, eright); + if (fright == null) { return null; } + if (fleft == null) { return null; } + return new BinaryExpression("!", fleft, fright); + } // and for =>, etc + else + { Vector invars = expr.innermostVariables(); + if (bound.containsAll(invars)) + { return expr; } + else + { System.err.println("!! Template where " + expr + " uses unbound variables " + + invars + " not in " + bound); + return null; + } + } + } + else + { Vector invars = expr.innermostVariables(); + if (bound.containsAll(invars)) + { return expr; } + else + { System.err.println("!! Template where " + expr + " uses unbound variables " + + invars + " not in " + bound); + return null; + } + } + } + + public Expression toUMLRSDSantecedent() { Vector bnd = new Vector(); return toUMLRSDSantecedent(bnd, null); @@ -324,7 +384,44 @@ public Expression toTargetExpression(Vector bound, Expression contextObj, Expres Expression scope = new BasicExpression(referredClass); Expression decl = new BinaryExpression(":", btexp, scope); - res = new BinaryExpression("#", decl, res); + if (leastchange) + { res = new BinaryExpression("#LC", decl, res); } + else + { res = new BinaryExpression("#", decl, res); } + + // System.out.println("TARGET ACTION for " + this + " IS " + res); + + return res; + } + + public Expression toUndoExpression(Vector bound, Expression contextObj, Expression setting) + { Expression res = setting; + Expression btexp = new BasicExpression(bindsTo); + boolean alreadybound = bound.contains(bindsTo + ""); + // System.out.println("BOUND = " + bound + " " + bindsTo); + + if (alreadybound) { } + else + { bound.add(bindsTo + ""); } + + for (int i = 0; i < part.size(); i++) + { PropertyTemplateItem p = (PropertyTemplateItem) part.get(i); + p.setEntity(referredClass); + Expression pexp = p.toUndoExpression(bound, btexp,null); + res = Expression.simplify("&",res,pexp,null); + } + + // res = Expression.simplify("&",res,where,null); + + if (alreadybound) + { return res; } + + /* Expression scope = new BasicExpression(referredClass); + Expression decl = new BinaryExpression(":", btexp, scope); + if (leastchange) + { res = new BinaryExpression("#LC", decl, res); } + else + { res = new BinaryExpression("#", decl, res); } */ // System.out.println("TARGET ACTION for " + this + " IS " + res); @@ -352,7 +449,11 @@ public Expression toTargetExpressionOp(Vector bound, Expression contextObj, Expr { return res; } Expression scope = new BasicExpression(referredClass); Expression decl = new BinaryExpression(":", btexp, scope); - res = new BinaryExpression("#", decl, res); + + if (leastchange) + { res = new BinaryExpression("#LC", decl, res); } + else + { res = new BinaryExpression("#", decl, res); } // System.out.println("TARGET ACTION for " + this + " IS " + res); return res; @@ -361,6 +462,9 @@ public Expression toTargetExpressionOp(Vector bound, Expression contextObj, Expr public String toString() { String res = bindsTo + " : " + referredClass + " { "; + if (leastchange) + { res = bindsTo + " <:= " + referredClass + " { "; } + for (int i = 0; i < part.size(); i++) { PropertyTemplateItem p = (PropertyTemplateItem) part.get(i); res = res + p; diff --git a/OperationDescription.java b/OperationDescription.java index 06e7296b..731c72f9 100644 --- a/OperationDescription.java +++ b/OperationDescription.java @@ -15,8 +15,10 @@ public class OperationDescription extends BehaviouralFeature { private Vector maintainOps = new Vector(); // extra ops for Dbi, in case of set - - + String opaction = ""; + String oprole = ""; + + public OperationDescription(String nme, Entity e, String op, String role) { // E is the entity being operated on, op the @@ -25,8 +27,10 @@ public OperationDescription(String nme, setEntity(e); setStereotypes(new Vector()); stereotypes.add(op); + opaction = op; if (role != null && !(role.equals(""))) { stereotypes.add(role); } + oprole = role; System.out.println("Action: " + op + " Stereotypes: " + stereotypes); @@ -68,7 +72,7 @@ else if (op.equals("list")) // no parameters else if (op.equals("get") || op.equals("delete")) // delete, get { Vector keys = e.getUniqueAttributes(); if (keys.size() == 0) - { System.err.println("!! ERROR: Cannot define operation get: no primary key"); + { System.err.println("!! ERROR: Cannot define operation get/delete: no primary key"); return; } else @@ -83,6 +87,8 @@ else if (op.equals("add")) else { Entity entity2 = ast.getEntity2(); Vector bkeys = entity2.getUniqueAttributes(); + if (bkeys.size() == 0) + { System.err.println("!! ERROR: no primary keys for: " + entity2); } Vector pars = new Vector(); pars.addAll(e.getUniqueAttributes()); pars.addAll(bkeys); @@ -98,6 +104,8 @@ else if (op.equals("remove")) else { Entity entity2 = ast.getEntity2(); Vector bkeys = entity2.getUniqueAttributes(); + if (bkeys.size() == 0) + { System.err.println("!! ERROR: no primary keys for: " + entity2); } Vector pars = new Vector(); pars.addAll(bkeys); setParameters(pars); @@ -118,7 +126,7 @@ public String getMaintainOps() public String getAction() { if (stereotypes.size() > 0) { return (String) stereotypes.get(0); } - return ""; + return opaction; } // should be the first one that isn't a standard stereotype public void saveData(PrintWriter out) @@ -168,7 +176,9 @@ public String getDbiParameterDec() private String getAndroidDbiCallList() { String res = ""; String ent = entity.getName(); - Vector pars = getParameters(); + // Vector pars = getParameters(); + Vector pars = entity.getAttributes(); + for (int i = 0; i < pars.size(); i++) { Attribute att = (Attribute) pars.get(i); Type t = att.getType(); @@ -181,12 +191,21 @@ else if ("double".equals(t.getName())) if (i < pars.size() - 1) { res = res + ", "; } } + + // if (pars.size() <= 1) + // { return res; } + return "new " + ent + "VO(" + res + ")"; } private String getDbiCallList() { String res = ""; Vector pars = getParameters(); + if (opaction.startsWith("delete")) + { Attribute att1 = (Attribute) pars.get(0); + return att1.getName(); + } + for (int i = 0; i < pars.size(); i++) { Attribute att = (Attribute) pars.get(i); Type t = att.getType(); @@ -202,13 +221,13 @@ else if ("double".equals(t.getName())) return res; } - public String getAndroidDbiOp() + public String getAndroidDbiOpCall() { // Op is: dbi.action + ename(pars); String pars = getAndroidDbiCallList(); return "dbi." + getODName() + "(" + pars + ");"; } // plus the role name in case of get/add/remove - public String getDbiOp() + public String getDbiOpCall() { // Op is: dbi.action + ename(pars); String pars = getDbiCallList(); return "dbi." + getODName() + "(" + pars + ");"; @@ -243,6 +262,144 @@ public String getODName(int i) { return action + ename; } } + public void androidDbiOp(PrintWriter out) + { String action = getStereotype(0); + String ename = entity.getName(); + ArrayList ents = new ArrayList(); + ents.add(ename); + ArrayList flds = new ArrayList(); + Vector pars = getParameters(); + for (int i = 0; i < pars.size(); i++) + { Attribute att = (Attribute) pars.get(i); + flds.add(att.getName()); + } + + if (action.equals("create")) + { androidDbiCreateOp(ename,out); } + else if (action.equals("delete")) + { androidDbiDeleteOp(ename,out); } + else if (action.equals("list")) + { androidDbiListOp(ename,out); } + else if (action.equals("searchBy") && stereotypes.size() > 1) + { String key = getStereotype(1); + androidDbiSearchByOp(ename,key,out); + } + else if (action.equals("edit")) + { androidDbiEditOp(ename,out); } + } + + public void androidDbiCreateOp(String ent, PrintWriter out) + { String entlc = ent.toLowerCase(); + Vector atts = entity.getAttributes(); + int natts = atts.size(); + out.println(" public void create" + ent + "(" + ent + "VO " + entlc + "vo)"); + out.println(" { database = getWritableDatabase();"); + out.println(" ContentValues _wr = new ContentValues(" + ent + "_NUMBER_COLS);"); + + for (int z = 0; z < natts; z++) + { Attribute att = (Attribute) atts.get(z); + String nmeatt = att.getName(); + String nup = nmeatt.toUpperCase(); + out.println(" _wr.put(" + ent + "_COLS[" + ent + "_COL_" + nup + "]," + + entlc + "vo.get" + nmeatt + "());"); + } + out.println(" database.insert(" + ent + "_TABLE_NAME," + + ent + "_COLS[1],_wr);"); + out.println(" }"); + } + + public void androidDbiDeleteOp(String ent, PrintWriter out) + { String entlc = ent.toLowerCase(); + + out.println(" public void delete" + ent + "(String " + entlc + "Id)"); + out.println(" { database = getWritableDatabase();"); + out.println(" String[] _args = new String[]{" + entlc + "Id};"); + out.println(" database.delete(" + ent + "_TABLE_NAME, \"" + entlc + "Id = ?\", _args);"); + out.println(" }"); + } + + public void androidDbiListOp(String ent, PrintWriter out) + { Vector atts = entity.getAttributes(); + int natts = atts.size(); + String entlc = ent.toLowerCase(); + + out.println(" public ArrayList<" + ent + "VO> list" + ent + "()"); + out.println(" { ArrayList<" + ent + "VO> res = new ArrayList<" + ent + "VO>();"); + out.println(" database = getReadableDatabase();"); + out.println(" Cursor cursor = database.query(" + ent + + "_TABLE_NAME," + ent + "_COLS,null,null,null,null,null);"); + out.println(" cursor.moveToFirst();"); + out.println(" while(!cursor.isAfterLast())"); + out.println(" { " + ent + "VO " + entlc + "vo = new " + ent + "VO();"); + for (int y = 0; y < natts; y++) + { Attribute att = (Attribute) atts.get(y); + String anme = att.getName(); + String getop = att.androidExtractOp(ent); + out.println(" " + entlc + "vo.set" + anme + "(" + getop + ");"); + } + out.println(" res.add(" + entlc + "vo);"); + out.println(" cursor.moveToNext();"); + out.println(" }"); + out.println(" cursor.close();"); + out.println(" return res;"); + out.println(" }"); + } + + public void androidDbiSearchByOp(String ent, String att, PrintWriter out) + { Vector atts = entity.getAttributes(); + + int natts = atts.size(); + String entlc = ent.toLowerCase(); + + out.println(" public ArrayList<" + ent + "VO> searchBy" + ent + att + "(String _val)"); + out.println(" { ArrayList<" + ent + "VO> res = new ArrayList<" + ent + "VO>();"); + out.println(" database = getReadableDatabase();"); + out.println(" String[] _args = new String[]{_val};"); + String allatts = "_id"; + for (int c = 0; c < natts; c++) + { Attribute ax = (Attribute) atts.get(c); + allatts = allatts + ", " + ax.getName(); + } + out.println(" Cursor cursor = database.rawQuery(\"select " + allatts + " from " + + ent + " where " + att + " = ?\", _args);"); + out.println(" cursor.moveToFirst();"); + out.println(" while(!cursor.isAfterLast())"); + out.println(" { " + ent + "VO " + entlc + "vo = new " + ent + "VO();"); + for (int y = 0; y < natts; y++) + { Attribute attx = (Attribute) atts.get(y); + String anme = attx.getName(); + String getop = attx.androidExtractOp(ent); + out.println(" " + entlc + "vo.set" + anme + "(" + getop + ");"); + } + out.println(" res.add(" + entlc + "vo);"); + out.println(" cursor.moveToNext();"); + out.println(" }"); + out.println(" cursor.close();"); + out.println(" return res;"); + out.println(" }"); + out.println(); + } + + public void androidDbiEditOp(String ent, PrintWriter out) + { String entlc = ent.toLowerCase(); + Vector atts = entity.getAttributes(); + int natts = atts.size(); + + out.println(" public void edit" + ent + "(" + ent + "VO " + entlc + "vo)"); + out.println(" { database = getWritableDatabase();"); + out.println(" ContentValues _wr = new ContentValues(" + ent + "_NUMBER_COLS);"); + for (int z = 0; z < natts; z++) + { Attribute att = (Attribute) atts.get(z); + String nmeatt = att.getName(); + String nup = nmeatt.toUpperCase(); + out.println(" _wr.put(" + ent + "_COLS[" + ent + "_COL_" + nup + "]," + + entlc + "vo.get" + nmeatt + "());"); + } + out.println(" String[] _args = new String[]{ " + entlc + "vo.get" + entlc + "Id() };"); + out.println(" database.update(" + ent + "_TABLE_NAME, _wr, \"" + entlc + "Id=?\", _args);"); + out.println(" }"); + } + public SQLStatement getSQL0() { String action = getStereotype(0); String ename = entity.getName(); @@ -386,7 +543,7 @@ else if (action.equals("remove")) public String getServletCode() { String res = ""; String sname = getODName(); - String dbiop = getDbiOp(); + String dbiop = getDbiOpCall(); String action = getStereotype(0); String ename = entity.getName(); @@ -742,12 +899,134 @@ public static void createWebServiceBean(Vector usecases, Vector entities, PrintW out.println("}\n\r\n\r"); } +public void iOSViewController(PrintWriter out) +{ String op = getAction(); + if (op.startsWith("create")) + { generateViewController(out); } + else if (op.startsWith("delete")) + { generateViewController(out); } + else if (op.startsWith("edit")) + { generateViewController(out); } + else if (op.startsWith("list")) + { IOSAppGenerator gen = new IOSAppGenerator(); + gen.listViewController(entity,out); + } + else + { System.err.println("No screen is defined yet for " + op); } +} + + public void generateViewController(PrintWriter out) + { // for createE, editE, deleteE + + String op = getAction(); + String ename = entity.getName(); + String ucname = op + ename; + String evc = ucname + "ViewController"; + // String evo = ename + "ValueObject"; + // String vo = evo.toLowerCase(); + String resvo = "result"; + String restype = ""; + String ebean = "ModelFacade"; + String bean = ebean.toLowerCase(); + Vector atts = getParameters(); + // Attribute res = uc.getResultParameter(); + + // String evocreate = createVOStatement(e,atts); + + out.println("import UIKit"); + out.println(); + out.println("class " + evc + " : UIViewController"); + out.println("{"); + out.println(" var " + bean + " : " + ebean + " = " + ebean + ".getInstance()"); + + String parlist = ""; + for (int x = 0; x < atts.size(); x++) + { Attribute att = (Attribute) atts.get(x); + // if (att.isInputAttribute()) + out.println(" @IBOutlet weak var " + att + "Input: UITextField!"); + + parlist = parlist + att.getName(); + if (x < atts.size() - 1) + { parlist = parlist + ", "; } + } + + /* if (res != null) + { out.println(" @IBOutlet weak var resultOutput: UILabel!"); + restype = res.getType().getSwift(); + } */ + + out.println(" var userId : String = " + "\"0\""); + out.println(); + out.println(" override func viewDidLoad()"); + out.println(" { super.viewDidLoad()"); + // out.println(" self." + elist + " = " + bean + "." + getlist + "()"); + out.println(" }"); + out.println(""); + + String attdecoder = " guard "; + boolean previous = false; + String localVars = ""; + + for (int x = 0; x < atts.size(); x++) + { Attribute att = (Attribute) atts.get(x); + // if (att.isInputAttribute()) + { if (previous) + { attdecoder = attdecoder + ", "; } + attdecoder = attdecoder + " let " + att + " = " + + Expression.unwrapSwift(att + "Input.text",att.getType()); + previous = true; + } + // else + // { Type atype = att.getType(); + // if (atype != null) + // { localVars = localVars + " var " + att + " : " + atype.getSwift() + "\n"; } + // } + } + attdecoder = attdecoder + " else { return }\n"; + + String updateScreen = ""; + + /* if (res != null) + { Attribute att = res; // (Attribute) atts.get(x); + // if (att.isOutput()) + { updateScreen = updateScreen + " " + att + "Output.text = String(" + att + ")"; + } + } */ + + out.println(" @IBAction func " + ucname + "(_ sender: Any) {"); + if (atts.size() > 0) + { out.println(attdecoder); } + // out.println(localVars); + // out.println(evocreate); + /* if (res != null) + { out.println(" var " + resvo + " : " + restype + " = " + bean + "." + ucname + "(" + parlist + ")"); + out.println(updateScreen); + } + else */ + { out.println(" " + bean + "." + ucname + "(" + parlist + ")"); } + out.println(" }"); + // } + + out.println(""); + + out.println(" override func didReceiveMemoryWarning()"); + out.println(" { super.didReceiveMemoryWarning() }"); + out.println(""); + out.println("}"); + } + public void androidScreen(PrintWriter out) { String op = getAction(); if (op.startsWith("create")) - { androidCreateScreen(op,out); } + { androidEditScreen(op,out); } + else if (op.startsWith("delete")) + { androidEditScreen(op,out); } else if (op.startsWith("edit")) { androidEditScreen(op,out); } + else if (op.startsWith("list")) + { androidListScreen(op,out); } + else if (op.startsWith("searchBy")) + { androidSearchByScreen(op,out); } else { System.err.println("No screen is defined yet for " + op); } } @@ -759,6 +1038,10 @@ public void androidCreateScreen(String op, PrintWriter out) String opcancel = op + ename + "Cancel"; String fullop = op + ename; + String oklabel = "OK"; + if (op.startsWith("delete")) + { oklabel = "Delete"; } + out.println(""); @@ -840,20 +1123,430 @@ public void androidEditScreen(String op, PrintWriter out) out.println(""); } -public void androidViewActivity(PrintWriter out) +public void androidListScreen(String op, PrintWriter out) +{ String ent = entity.getName(); + String viewname = "View" + op + ent; + + out.println(""); + + out.println(" "); + out.println(""); + out.println(); +} + +public void androidSearchByScreen(String op, PrintWriter out) +{ String ent = entity.getName(); + String viewname = "ViewsearchBy" + ent + oprole; + String label = Named.capitalise(oprole); + String opok = "searchBy" + ent + oprole + "OK"; + String opcancel = "searchBy" + ent + oprole + "Cancel"; + Attribute att = entity.getAttribute(oprole); + String field = "searchBy" + ent + oprole + "Field"; + + out.println(""); + out.println(" "); + out.println(" "); + + out.println(" "); + + out.println(" "); + + out.println(" "); + out.println(""); + out.println(); +} + public static void androidTableLayoutForOp(String op, Vector atts, Attribute res, PrintWriter out) + { out.println(""); + for (int x = 0; x < atts.size(); x++) + { Attribute att = (Attribute) atts.get(x); + String attnme = att.getName(); + String label = Named.capitalise(attnme); + + String attlabel = op + attnme + "Label"; + String attfield = op + attnme + "Field"; + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(); + } + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(); + if (res != null) + { out.println(" "); + out.println(" "); + out.println(" android:layout_span=\"5\" />"); + out.println(" "); + } + out.println(""); + } + + public static void androidTableLayoutForOps(String op, Vector atts, Attribute res, Vector usecases, + PrintWriter out) + { out.println(""); + for (int x = 0; x < atts.size(); x++) + { Attribute att = (Attribute) atts.get(x); + String attnme = att.getName(); + String label = Named.capitalise(attnme); + + String attlabel = op + attnme + "Label"; + String attfield = op + attnme + "Field"; + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(); + } + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(); + if (res != null) + { out.println(" "); + out.println(" "); + out.println(" android:layout_span=\"5\" />"); + out.println(" "); + } + + for (int j = 0; j < usecases.size(); j++) + { UseCase extensionuc = (UseCase) usecases.get(j); + String ucop = extensionuc.getName(); + Vector ucatts = extensionuc.getParameters(); + Attribute ucres = extensionuc.getResultParameter(); + for (int x = 0; x < ucatts.size(); x++) + { Attribute att = (Attribute) ucatts.get(x); + String attnme = att.getName(); + String label = Named.capitalise(attnme); + + String attlabel = ucop + attnme + "Label"; + String attfield = ucop + attnme + "Field"; + out.println(" "); + out.println(" "); + out.println(" "); + out.println(" "); + out.println(); + } + out.println(" "); + out.println(" "); + if (ucres != null) + { out.println(" "); + out.println(" android:layout_span=\"3\" />"); + out.println(" />"); + } + out.println(" "); + out.println(); + } + out.println(""); + } + +public static void androidOpViewActivity(String op, Vector pars, Attribute res, Vector extensions, PrintWriter out) +{ // Entity ent = getEntity(); + // String entname = ent.getName(); + // String fullop = op + entname; + String beanclass = op + "Bean"; + String bean = beanclass.toLowerCase(); + + out.println("package com.example.app;\n"); + out.println(); + out.println("import android.os.Bundle;"); + out.println("import android.app.Activity;"); + out.println("import android.view.View;"); + out.println("import android.util.Log;"); + out.println("import android.widget.EditText;\n\r"); + out.println(); + + out.println("public class " + op + "Activity extends Activity"); + out.println("{ " + beanclass + " " + bean + ";"); + + for (int p = 0; p < extensions.size(); p++) + { UseCase extension = (UseCase) extensions.get(p); + String extop = extension.getName(); + String extbeanclass = extop + "Bean"; + String extbean = extbeanclass.toLowerCase(); + out.println(" " + extbeanclass + " " + extbean + ";"); + } + out.println(); + + // Vector pars = getParameters(); + for (int x = 0; x < pars.size(); x++) + { Attribute par = (Attribute) pars.get(x); + String pnme = par.getName(); + String tfnme = pnme + "TextField"; + String dname = pnme + "Data"; + out.println(" EditText " + tfnme + ";"); + out.println(" String " + dname + " = \"\";"); + } + + if (res != null) + { out.println(" TextView " + op + "Result;"); } + + for (int p = 0; p < extensions.size(); p++) + { UseCase extension = (UseCase) extensions.get(p); + String extop = extension.getName(); + Vector extpars = extension.getParameters(); + Attribute extres = extension.getResultParameter(); + + for (int x = 0; x < extpars.size(); x++) + { Attribute extpar = (Attribute) extpars.get(x); + String pnme = extpar.getName(); + String tfnme = pnme + "TextField"; + String dname = pnme + "Data"; + out.println(" EditText " + tfnme + ";"); + out.println(" String " + dname + " = \"\";"); + } + if (extres != null) + { out.println(" TextView " + extop + "Result;"); } + } + + out.println(); + out.println(); + out.println(" @Override"); + out.println(" protected void onCreate(Bundle bundle)"); + out.println(" { super.onCreate(bundle);"); + out.println(" setContentView(R.layout." + op + "_layout);"); + + for (int x = 0; x < pars.size(); x++) + { Attribute par = (Attribute) pars.get(x); + String pnme = par.getName(); + String tfnme = pnme + "TextField"; + out.println(" " + tfnme + " = (EditText) findViewById(R.id." + op + pnme + "Field);"); + } + if (res != null) + { out.println(" " + op + "Result = (TextView) findViewById(R.id." + op + "Result);"); } + + out.println(" " + bean + " = new " + beanclass + "(this);"); + + for (int p = 0; p < extensions.size(); p++) + { UseCase extension = (UseCase) extensions.get(p); + String extop = extension.getName(); + String extbeanclass = extop + "Bean"; + Attribute extres = extension.getResultParameter(); + String extbean = extbeanclass.toLowerCase(); + Vector extpars = extension.getParameters(); + for (int y = 0; y < extpars.size(); y++) + { Attribute par = (Attribute) extpars.get(y); + String pnme = par.getName(); + String tfnme = pnme + "TextField"; + out.println(" " + tfnme + " = (EditText) findViewById(R.id." + extop + pnme + "Field);"); + } + if (extres != null) + { out.println(" " + extop + "Result = (TextView) findViewById(R.id." + extop + "Result);"); } + + out.println(" " + extbean + " = new " + extbeanclass + "(this);"); + } + out.println(" }\n\r"); + out.println(); // for edit, the principal primary key does not have an EditText + + out.println(" public void " + op + "OK(View _v) "); + out.println(" {"); + for (int x = 0; x < pars.size(); x++) + { Attribute att = (Attribute) pars.get(x); + String aname = att.getName(); + String tfnme = aname + "TextField"; + String dname = aname + "Data"; + out.println(" " + dname + " = " + tfnme + ".getText() + \"\";"); + out.println(" " + bean + ".set" + aname + "(" + dname + ");"); + } + out.println(" if (" + bean + ".is" + op + "error())"); + out.println(" { Log.w(getClass().getName(), " + bean + ".errors()); }"); + out.println(" else"); + if (res != null) + { out.println(" { " + op + "Result.setText(" + bean + "." + op + "()); }"); } + else + { out.println(" { " + bean + "." + op + "(); }"); } + + out.println(" }\n\r"); + out.println(); + + out.println(" public void " + op + "Cancel(View _v) {}"); + + for (int p = 0; p < extensions.size(); p++) + { UseCase extension = (UseCase) extensions.get(p); + String extop = extension.getName(); + Vector extpars = extension.getParameters(); + Attribute extres = extension.getResultParameter(); + + String extbeanclass = extop + "Bean"; + String extbean = extbeanclass.toLowerCase(); + + out.println(" public void " + extop + "OK(View _v) "); + out.println(" {"); + for (int x = 0; x < extpars.size(); x++) + { Attribute att = (Attribute) extpars.get(x); + String aname = att.getName(); + String tfnme = aname + "TextField"; + String dname = aname + "Data"; + out.println(" " + dname + " = " + tfnme + ".getText() + \"\";"); + out.println(" " + extbean + ".set" + aname + "(" + dname + ");"); + } + out.println(" if (" + extbean + ".is" + op + "error())"); + out.println(" { Log.w(getClass().getName(), " + extbean + ".errors()); }"); + out.println(" else"); + if (extres != null) + { out.println(" { " + extop + "Result.setText(" + extbean + "." + extop + "()); }"); } + else + { out.println(" { " + extbean + "." + extop + "(); }"); } + + out.println(" }\n\r"); + out.println(); + } + + out.println("}"); +} + + + +public void androidViewActivity(String systemName, PrintWriter out) { String op = getAction(); + AndroidAppGenerator gen = new AndroidAppGenerator(); + if (op.startsWith("create")) - { androidCreateViewActivity(op,out); } + { androidCreateViewActivity(op,systemName,out); } + else if (op.startsWith("delete")) + { gen.androidDeleteViewActivity(op,entity,out); } + else if (op.startsWith("edit")) + { gen.androidEditViewActivity(op,entity,out); } + else if (op.startsWith("list")) + { gen.listViewController(entity,out); } + else if (op.startsWith("searchBy")) + { androidSearchByViewActivity(op,systemName,out); } } -public void androidCreateViewActivity(String op, PrintWriter out) +public void androidCreateViewActivity(String op, String systemName, PrintWriter out) { Entity ent = getEntity(); String entname = ent.getName(); String fullop = op + entname; String beanclass = entname + "Bean"; String bean = beanclass.toLowerCase(); - out.println("package com.example.app;\n"); + out.println("package com.example." + systemName + ";\n"); out.println(); out.println("import android.os.Bundle;"); out.println("import android.app.Activity;"); @@ -879,7 +1572,7 @@ public void androidCreateViewActivity(String op, PrintWriter out) out.println(" @Override"); out.println(" protected void onCreate(Bundle bundle)"); out.println(" { super.onCreate(bundle);"); - out.println(" setContentView(R.layout." + fullop + ");"); + out.println(" setContentView(R.layout." + fullop + "_layout);"); for (int x = 0; x < pars.size(); x++) { Attribute par = (Attribute) pars.get(x); @@ -889,7 +1582,7 @@ public void androidCreateViewActivity(String op, PrintWriter out) } out.println(" " + bean + " = new " + beanclass + "(this);"); out.println(" }\n\r"); - out.println(); + out.println(); // for edit, the principal primary key does not have an EditText out.println(" public void " + fullop + "OK(View _v) "); out.println(" {"); @@ -922,9 +1615,18 @@ public static void androidCreateMenu(Vector ops, PrintWriter out) out.println(); for (int x = 0; x < ops.size(); x++) - { OperationDescription op = (OperationDescription) ops.get(x); - op.androidTabItem(out); + { if (ops.get(x) instanceof OperationDescription) + { OperationDescription op = (OperationDescription) ops.get(x); + op.androidTabItem(out); + } + else if (ops.get(x) instanceof UseCase) + { UseCase uc = (UseCase) ops.get(x); + if (uc.includedIn.size() == 0 && uc.extensionOf.size() == 0) + { uc.androidTabItem(out); } + } } + + out.println(); out.println(""); } @@ -943,8 +1645,8 @@ public static void androidCreateMainActivity(Vector ops, PrintWriter out) out.println("import android.app.FragmentTransaction;"); out.println("import android.view.Menu;"); out.println("import android.view.MenuItem;"); - out.println("import android.view.ActionBar;"); - out.println("import android.view.ActionBar.Tab;"); + out.println("import android.app.ActionBar;"); + out.println("import android.app.ActionBar.Tab;"); out.println(""); out.println("public class MainActivity extends Activity implements ActionBar.TabListener"); out.println("{ "); @@ -953,18 +1655,34 @@ public static void androidCreateMainActivity(Vector ops, PrintWriter out) out.println(" @Override"); out.println(" protected void onCreate(Bundle bundle)"); out.println(" { super.onCreate(bundle);"); - out.println(" setContentView(R.layout.mainActivity);"); + out.println(" setContentView(R.layout.activity_main);"); out.println(" ActionBar bar = this.getActionBar();"); + out.println(" bar.setTitle(\"My application\");"); out.println(" bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);"); for (int x = 0; x < ops.size(); x++) - { OperationDescription op = (OperationDescription) ops.get(x); - String pnme = op.getName(); - String tfnme = pnme + "Tab"; - out.println(" Tab " + tfnme + " = bar.newTab();"); - out.println(" " + tfnme + ".setText(" + pnme + ");"); - out.println(" " + tfnme + ".setTabListener(this);"); - out.println(" bar.addTab(" + tfnme + ");"); + { if (ops.get(x) instanceof OperationDescription) + { OperationDescription op = (OperationDescription) ops.get(x); + String pnme = op.getName(); + String tfnme = pnme + "Tab"; + String tabname = Named.capitalise(pnme); + out.println(" Tab " + tfnme + " = bar.newTab();"); + out.println(" " + tfnme + ".setText(\"" + tabname + "\");"); + out.println(" " + tfnme + ".setTabListener(this);"); + out.println(" bar.addTab(" + tfnme + ");"); + } + else if (ops.get(x) instanceof UseCase) + { UseCase op = (UseCase) ops.get(x); + if (op.includedIn.size() == 0 && op.extensionOf.size() == 0) + { String pnme = op.getName(); + String tfnme = pnme + "Tab"; + String tabname = Named.capitalise(pnme); + out.println(" Tab " + tfnme + " = bar.newTab();"); + out.println(" " + tfnme + ".setText(\"" + tabname + "\");"); + out.println(" " + tfnme + ".setTabListener(this);"); + out.println(" bar.addTab(" + tfnme + ");"); + } + } } out.println(" }"); @@ -972,16 +1690,28 @@ public static void androidCreateMainActivity(Vector ops, PrintWriter out) out.println(" @Override"); out.println(" public void onTabSelected(Tab tab, FragmentTransaction frag) "); out.println(" {"); - out.println(" switch (tab.getItemId()) {"); for (int x = 0; x < ops.size(); x++) - { OperationDescription op = (OperationDescription) ops.get(x); - String opname = op.getName(); - out.println(" case R.id." + opname + ":"); - out.println(" Intent " + opname + "Intent = new Intent(this,View" + opname + ".class);"); - out.println(" startActivity(" + opname + "Intent);"); - out.println(" return;"); - } - out.println(" }"); + { if (ops.get(x) instanceof OperationDescription) + { OperationDescription op = (OperationDescription) ops.get(x); + String opname = op.getName(); + String tabname = Named.capitalise(opname); + out.println(" if (\"" + tabname + "\".equals(tab.getText())) "); + out.println(" { Intent " + opname + "Intent = new Intent(this, View" + opname + ".class);"); + out.println(" startActivity(" + opname + "Intent);"); + out.println(" return; }"); + } + else if (ops.get(x) instanceof UseCase) + { UseCase op = (UseCase) ops.get(x); + if (op.extensionOf.size() == 0 && op.includedIn.size() == 0) + { String opname = op.getName(); + String capsname = Named.capitalise(opname); + out.println(" if (\"" + capsname + "\".equals(tab.getText())) "); + out.println(" { Intent " + opname + "Intent = new Intent(this, " + opname + "Activity.class);"); + out.println(" startActivity(" + opname + "Intent);"); + out.println(" return; }"); + } + } + } out.println(" }"); out.println(); out.println(" @Override"); @@ -992,7 +1722,7 @@ public static void androidCreateMainActivity(Vector ops, PrintWriter out) out.println("}"); } - +/* public void androidListScreen(String op, PrintWriter out) { String nme = getName(); String viewname = "View" + nme; @@ -1014,8 +1744,65 @@ public void androidListScreen(String op, PrintWriter out) out.println(" "); out.println(""); -} - +} */ + + public void androidSearchByViewActivity(String op, String systemName, PrintWriter out) + { String ename = entity.getName(); + String evc = "ViewsearchBy" + ename + oprole; + String evo = ename + "VO"; + String ebean = "ModelFacade"; + String bean = "model"; + Vector atts = entity.getAttributes(); + String elist = ename.toLowerCase() + "List"; + String getlist = "searchBy" + ename + oprole; + String pnme = "searchBy" + ename + oprole + "Field"; + + out.println("package com.example." + systemName + ";"); + out.println(); + out.println("import android.os.Bundle;"); + out.println("import android.app.ListActivity;"); + out.println("import android.view.View;"); + out.println("import android.widget.ArrayAdapter;"); + out.println("import android.widget.ListView;"); + out.println("import android.widget.TextView;"); + out.println("import java.util.ArrayList;"); + out.println("import java.util.List;"); + out.println(); + out.println("public class " + evc + " extends ListActivity"); + out.println("{ private ModelFacade model;"); + out.println(); + out.println(" ArrayList<" + evo + "> " + elist + ";"); + String tfnme = pnme + "Text"; + String dname = pnme + "Data"; + out.println(" EditText " + tfnme + ";"); + out.println(" String " + dname + " = \"\";"); + out.println(); + out.println(" @Override"); + out.println(" protected void onCreate(Bundle savedInstanceState)"); + out.println(" { super.onCreate(savedInstanceState);"); + out.println(" setContentView(R.layout.searchBy" + ename + oprole + "_layout);"); + out.println(" model = ModelFacade.getInstance(this);"); + out.println(" " + tfnme + " = (EditText) findViewById(R.id." + pnme + ");"); + out.println(" " + elist + " = new ArrayList();"); + out.println(" ArrayAdapter adapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1," + elist + ");"); + out.println(" setListAdapter(adapter);"); + out.println(" }"); + out.println(); + + out.println(" public void searchBy" + ename + oprole + "OK(View _v) "); + out.println(" {"); + out.println(" " + dname + " = " + tfnme + ".getText() + \"\";"); + out.println(" " + elist + " = model.searchBy" + ename + oprole + "(" + dname + ");"); + out.println(" }"); + out.println(); + out.println(" public void searchBy" + ename + oprole + "Cancel(View _v) "); + out.println(" { } // go back to main screen"); + out.println(); + out.println(" public void onListItemClick(ListView parent, View v, int position, long id)"); + out.println(" { model.setSelected" + ename + "(position); }"); + out.println(); + out.println("}"); + } } diff --git a/OutPatternElement.java b/OutPatternElement.java index eb66bf7c..15bed195 100644 --- a/OutPatternElement.java +++ b/OutPatternElement.java @@ -15,6 +15,7 @@ public class OutPatternElement { Attribute variable; Vector bindings; // Binding boolean isDefault = false; // true for the first output element + Expression condition = null; public OutPatternElement(Attribute att) { variable = att; @@ -30,6 +31,18 @@ public void setDefault(boolean def) public void addBinding(Binding ipe) { bindings.add(ipe); } + public void setCondition(Expression cond) + { condition = cond; } + + public Expression getCondition() + { return condition; } + + public Attribute getVariable() + { return variable; } + + public Vector getBindings() + { return bindings; } + public String toString() { String res = variable.getName() + " : MM2!" + variable.getType() + " (\n"; for (int i = 0; i < bindings.size(); i++) diff --git a/Pattern.java b/Pattern.java index 20e2650c..ee88e6d8 100644 --- a/Pattern.java +++ b/Pattern.java @@ -166,7 +166,8 @@ public Vector variablesUsedIn() // but should count let and ->iterate variables - public Expression toGuardCondition(Vector bound, Expression contextObj, Expression post) + public Expression toGuardCondition(Vector bound, Expression contextObj, Expression post, + Entity tr) { return null; } public Expression toSourceExpression(Vector bound, Expression contextObj) @@ -175,6 +176,9 @@ public Expression toSourceExpression(Vector bound, Expression contextObj) public Expression toTargetExpression(Vector bound, Expression contextObj) { return null; } + public Expression toUndoExpression(Vector bound, Expression contextObj) + { return null; } + public Expression toSourceExpressionOp(Vector bound, Expression contextObj) { return null; } @@ -226,9 +230,16 @@ else if (conj instanceof ConditionalExpression) res.addAll(q1); res.addAll(q2); } + else if (conj instanceof UnaryExpression && ((UnaryExpression) conj).operator.equals("not")) + { UnaryExpression uexp = (UnaryExpression) conj; + Expression arg = uexp.getArgument(); + Pattern notpatt = new Pattern(); + notpatt.addPredicate(arg); + res.addAll(notpatt.allRuleCalls(rules)); + } } return res; - } // and negation, conditionals, ->forAll + } public Pattern expandWhenCalls(Vector oldrules, java.util.Map leafrules, java.util.Map guards) { Vector newpredicate = new Vector(); @@ -243,6 +254,11 @@ public Pattern expandWhenCalls(Vector oldrules, java.util.Map leafrules, java.ut { Vector leafs = (Vector) leafrules.get(r); Expression res = new BasicExpression(false); + if (leafs == null) + { newpredicate.add(conj); + continue; + } + for (int k = 0; k < leafs.size(); k++) { Relation rk = (Relation) leafs.get(k); BasicExpression rkcall = new BasicExpression(rk.getName()); @@ -274,7 +290,7 @@ public Pattern expandWhenCalls(Vector oldrules, java.util.Map leafrules, java.ut { newpredicate.add(conj); } } return new Pattern(newpredicate); - } + } // and other cases, disjunctions etc of calls. public Pattern expandWhereCalls(Vector oldrules, java.util.Map leafrules, java.util.Map guards) { Vector newpredicate = new Vector(); @@ -322,7 +338,7 @@ public Pattern expandWhereCalls(Vector oldrules, java.util.Map leafrules, java.u { newpredicate.add(conj); } } return new Pattern(newpredicate); - } + } // and other cases. public Vector whenToExp(Vector bound, Vector rules, Vector entities) { // R(s,t) is r$trace : s.traces$R$p1 & t = r$trace.p2 @@ -364,7 +380,8 @@ public Vector whenToExp(Vector bound, Vector rules, Vector entities) res.clear(); res.addAll(newres); } - else if (conj != null && (conj instanceof BinaryExpression) && ((BinaryExpression) conj).isRuleCallDisjunction(rules)) + else if (conj != null && (conj instanceof BinaryExpression) && + ((BinaryExpression) conj).isRuleCallDisjunction(rules)) { Vector disjs = ((BinaryExpression) conj).allDisjuncts(); Vector newres = new Vector(); @@ -395,15 +412,15 @@ else if (conj != null && Pattern pd = new Pattern(); pd.addPredicate(disj); Vector pdcases = pd.whenToExp(bound,rules,entities); - alldisjuncts.addAll(pdcases); + alldisjuncts.addAll(pdcases); + } - for (int j = 0; j < res.size(); j++) - { Expression ante = (Expression) res.get(j); - for (int m = 0; m < alldisjuncts.size(); m++) - { Expression disjm = (Expression) alldisjuncts.get(m); - Expression newante = Expression.simplify("&", ante, disjm, null); - newres.add(newante); - } + for (int j = 0; j < res.size(); j++) + { Expression ante = (Expression) res.get(j); + for (int m = 0; m < alldisjuncts.size(); m++) + { Expression disjm = (Expression) alldisjuncts.get(m); + Expression newante = Expression.simplify("&", ante, disjm, null); + newres.add(newante); } } res.clear(); @@ -427,6 +444,7 @@ else if (conj != null && return res; } // also add parameters of call to bound variables with predicate p:T if not in bound + // cases of quantifiers? Negation? ConditionalExpressions? public Vector checkWhen(Vector bound, Vector rules, Vector entities) { // R(s,t) is r$trace : R$trace # s = r$trace.p1 & t = r$trace.p2 @@ -445,7 +463,7 @@ public Vector checkWhen(Vector bound, Vector rules, Vector entities) { BasicExpression be = (BasicExpression) conj; e = be.checkWhen(entities,bound); - // System.out.println("RULE TEST: " + e); + // System.out.println("RULE TEST for guard: " + e); Vector pars = be.getParameters(); for (int p = 0; p < pars.size(); p++) @@ -468,7 +486,8 @@ public Vector checkWhen(Vector bound, Vector rules, Vector entities) res.clear(); res.addAll(newres); } - else if (conj != null && (conj instanceof BinaryExpression) && ((BinaryExpression) conj).isRuleCallDisjunction(rules)) + else if (conj != null && (conj instanceof BinaryExpression) && + ((BinaryExpression) conj).isRuleCallDisjunction(rules)) { Vector disjs = ((BinaryExpression) conj).allDisjuncts(); Vector newres = new Vector(); @@ -487,6 +506,27 @@ else if (conj != null && (conj instanceof BinaryExpression) && ((BinaryExpressio res.clear(); res.addAll(newres); } // also case of negated call + else if (conj != null && (conj instanceof BinaryExpression) && + ("or".equals(((BinaryExpression) conj).operator))) + { Vector disjs = ((BinaryExpression) conj).allDisjuncts(); + + Vector newres = new Vector(); + + for (int k = 0; k < disjs.size(); k++) + { // BasicExpression disj = (BasicExpression) disjs.get(k); + Expression callk = (Expression) disjs.get(k); + // disj.checkWhen(entities,bound); + // System.out.println("*** All disjuncts = " + callk); + + for (int j = 0; j < res.size(); j++) + { Expression ante = (Expression) res.get(j); + Expression newante = Expression.simplify("&", ante, callk, null); + newres.add(newante); + } + } + res.clear(); + res.addAll(newres); + } // also case of negated call else { Vector newres = new Vector(); diff --git a/PrimitiveDomain.java b/PrimitiveDomain.java index 1bf1edca..a0ff06b5 100644 --- a/PrimitiveDomain.java +++ b/PrimitiveDomain.java @@ -56,6 +56,10 @@ public Expression toTargetExpression(Vector bound) { return new BasicExpression(true); } + public Expression toUndoExpression(Vector bound) + { return new BasicExpression(true); + } + public Expression toSourceExpressionOp(Vector bound) { return new BasicExpression(true); } @@ -63,7 +67,7 @@ public Expression toTargetExpressionOp(Vector bound) { return new BasicExpression(true); } - public Expression toGuardCondition(Vector bound, Expression e) + public Expression toGuardCondition(Vector bound, Expression e, Entity tr) { return new BinaryExpression(rootVariable); // not needed if variable is bound? } diff --git a/PropertyTemplateItem.java b/PropertyTemplateItem.java index 63da37df..27844d2c 100644 --- a/PropertyTemplateItem.java +++ b/PropertyTemplateItem.java @@ -93,7 +93,7 @@ public Expression toGuardCondition(Vector bound, Expression contextObj, Expressi // referredProperty = template, as UML-RSDS expression Expression result = new BasicExpression(true); if (referredProperty == null) - { System.err.println(">>> No feature defined for property template item: " + this); + { System.err.println(">>>ERROR: invalid feature in property template item: " + this); return result; } @@ -122,7 +122,8 @@ else if (template != null) Expression xexp = new BasicExpression(x); result = new BinaryExpression(op, xexp, fexp); - if (template.isEmpty()) { } + if (template.isEmpty()) + { result = new BinaryExpression("&", result, post); } else { Expression andcond = template.toGuardCondition(bound,xexp,post); result = new BinaryExpression("&", result, andcond); @@ -272,6 +273,61 @@ else if (template != null) return result; } + public Expression toUndoExpression(Vector bound, Expression contextObj, Expression setting) + { // Expresses inverse of the expression, as UML-RSDS expression + + Expression result = new BasicExpression(true); + + if (referredProperty == null) + { System.err.println("No feature defined for " + this); + return result; + } + + BasicExpression fexp = new BasicExpression(contextObj, referredProperty); + String op = "="; + if (referredProperty.isMultiple()) + { op = "/:"; } + + if (value != null) + { if (value.isVariable()) + { // Expression valueexp = new BasicExpression(value); + if (bound.contains(value + "")) + { if ("=".equals(op)) + { } + else + { result = new BinaryExpression(op, value, fexp); } + } + else // should not occur + { result = new BinaryExpression(op, value, fexp); + bound.add(value + ""); + } + } + else // just a value expression + { } + } + else if (template != null) + { // Entity f = template.getEntity(); + Attribute x = template.bindsTo; + Expression xexp = new BasicExpression(x); + + // Expression setting; + if (referredProperty.isMultiple()) + { setting = new BinaryExpression("/:", xexp, fexp); } + else + { } + + // if (template.isEmpty()) + // { bound.add(x.getName()); + // result = new BinaryExpression("&", result, setting); + // } + // else + { Expression andcond = template.toUndoExpression(bound,xexp,setting); + result = Expression.simplifyAnd(result, andcond); + } + } + return result; + } + public Expression toTargetExpressionOp(Vector bound, Expression contextObj, Expression setting) { // Expresses referredProperty = value, or // referredProperty = template, as UML-RSDS expression diff --git a/RectData.java b/RectData.java index 58304c11..0238071b 100644 --- a/RectData.java +++ b/RectData.java @@ -110,6 +110,13 @@ else if (e.isActive()) if (fm.stringWidth("<>") + (namex - sourcex) >= width) { width = fm.stringWidth("<>") + (namex - sourcex) + 5; } } + else if (e.isExternal() || e.isExternalApp()) + { g.drawString(label,namex,namey); + g.drawString("<>",namex,namey-5); + FontMetrics fm = g.getFontMetrics(); + if (fm.stringWidth("<>") + (namex - sourcex) >= width) + { width = fm.stringWidth("<>") + (namex - sourcex) + 5; } + } else { g.drawString(label,namex,namey); } diff --git a/Relation.java b/Relation.java index be58e485..60a04b03 100644 --- a/Relation.java +++ b/Relation.java @@ -114,11 +114,11 @@ else if (!isTopLevel && !r.isTopLevel) { } Domain rdomain = r.getDomain(dname); if (rdomain == null) - { newdomains.add(d); } + { newdomains.add(d); } // in old domain, not in r else { Domain newdomain = d.overrideBy(rdomain); if (newdomain != null) - { newdomains.add(newdomain); } + { newdomains.add(newdomain); } // old version combined with new } } @@ -128,7 +128,7 @@ else if (!isTopLevel && !r.isTopLevel) { } Domain mydomain = getDomain(rdname); if (mydomain == null) - { newdomains.add(rd); } + { newdomains.add(rd); } // new in the new rule } Relation res = new Relation(r.name, transformation); @@ -223,7 +223,9 @@ public Domain getDomain(String nme) public void addVariable(Attribute att) - { variable.add(att); } + { if (variable.contains(att)) {} + else { variable.add(att); } + } public void addVariables(Vector atts) { variable.addAll(atts); } @@ -270,9 +272,9 @@ public Vector recursiveWhenCalls(Vector rules, Vector seen) res.add(wc); String wcd = wc.data; if (wcd.equals(name)) - { System.err.println("!!! ERROR: calling relation " + name + " recursively"); } + { System.err.println("!!! ERROR: calling relation " + name + " recursively via when"); } else if (seen.contains(wcd)) - { System.err.println("!!! ERROR: calling cycle of relations with " + wcd); } + { System.err.println("!!! ERROR: calling cycle of relations in when with " + wcd); } else { Relation r = (Relation) NamedElement.findByName(wcd,rules); if (r != null) @@ -306,9 +308,9 @@ public Vector recursiveWhereCalls(Vector rules, Vector seen) res.add(wc); String wcd = wc.data; if (wcd.equals(name)) - { System.err.println("!!! ERROR: calling relation " + name + " recursively"); } + { System.err.println("!!! ERROR: calling relation " + name + " recursively in where"); } else if (seen.contains(wcd)) - { System.err.println("!!! ERROR: calling cycle of relations with " + wcd); } + { System.err.println("!!! ERROR: calling cycle of relations in where with " + wcd); } else { Relation r = (Relation) NamedElement.findByName(wcd,rules); if (r != null) @@ -435,7 +437,7 @@ public Map getCallGraph(Map res) Set calls = new HashSet(); Vector ops = new Vector(); - // assume no calls *within* the domains or variable initialisations + // assume no calls *within* variable initialisations for (int j = 0; j < domain.size(); j++) { Domain d = (Domain) domain.get(j); @@ -466,7 +468,7 @@ public Map getCallGraph(Map res) return res; } - + // EFI? public void addTraceEntity(Vector entities, Vector assocs) { Entity e = getTraceEntity(assocs); @@ -477,12 +479,15 @@ public void addTraceEntity(Vector entities, Vector assocs) public Entity getTraceEntity(Vector assocs) { String ename = getName() + "$trace"; Vector atts = new Vector(); + Vector seen = new Vector(); Entity res = new Entity(ename); for (int j = 0; j < domain.size(); j++) { Domain d = (Domain) domain.get(j); - if (d.rootVariable != null) + if (d.rootVariable != null && !(seen.contains(d.rootVariable.getName()))) { Attribute att = d.rootVariable; + seen.add(att.getName()); + BasicExpression dini = new BasicExpression("null"); dini.umlkind = Expression.VALUE; dini.type = att.getType(); @@ -491,6 +496,10 @@ public Entity getTraceEntity(Vector assocs) { att.setInitialExpression(dini); att.setInitialValue("null"); } + else if (Type.isEntityCollection(dini.type)) + { att.setInitialExpression(new SetExpression()); + att.setInitialValue("new Vector()"); + } atts.add(att); // res.addAttribute(att); @@ -505,6 +514,20 @@ public Entity getTraceEntity(Vector assocs) Association invast = ast.generateInverseAssociation(); ent2.addAssociation(invast); } + else if (Type.isEntityCollection(dini.type)) + { Entity ent2 = dini.type.elementType.getEntity(); + Association ast = new Association(res,ent2,Association.MANY,Association.MANY, + "traces$" + getName() + "$" + att.getName(),att.getName()); + if (Type.isSequenceType(dini.type)) + { ast.setOrdered(true); } + + assocs.add(ast); + res.addAssociation(ast); + if (att.isSource()) + { ast.setSource(true); } + Association invast = ast.generateInverseAssociation(); + ent2.addAssociation(invast); + } else { res.addAttribute(att); } } @@ -541,8 +564,10 @@ public Entity getTraceEntity(Vector assocs) wdini.elementType = watt.getElementType(); // res.addAttribute(watt); - if (wdini.type.isEntity()) - { Entity ent2 = wdini.type.getEntity(); + if (wdini.type.isEntity() && !(seen.contains(watt.getName()))) + { seen.add(watt.getName()); + + Entity ent2 = wdini.type.getEntity(); watt.setInitialExpression(wdini); watt.setInitialValue("null"); Association ast = new Association(res,ent2,Association.MANY,Association.ONE, @@ -552,6 +577,27 @@ public Entity getTraceEntity(Vector assocs) Association invast = ast.generateInverseAssociation(); ent2.addAssociation(invast); } + else if (Type.isEntityCollection(wdini.type) && !(seen.contains(watt.getName()))) + { seen.add(watt.getName()); + Entity ent2 = wdini.elementType.getEntity(); + SetExpression initexp = new SetExpression(); + watt.setInitialExpression(initexp); + watt.setInitialValue("new Vector()"); + Association ast = + new Association(res,ent2,Association.MANY,Association.MANY, + "traces$" + getName() + "$" + watt.getName(),watt.getName()); + if (Type.isSequenceType(wdini.type)) + { ast.setOrdered(true); + initexp.setOrdered(true); + } + assocs.add(ast); + res.addAssociation(ast); + // if (att.isSource()) + // { ast.setSource(true); } + Association invast = ast.generateInverseAssociation(); + ent2.addAssociation(invast); + } + } // actually assocs. - addRole? /* for (int f = 0; f < whenvars.size(); f++) @@ -611,7 +657,9 @@ public Vector targetVariables() Vector tvars = new Vector(); for (int i = 0; i < tatts.size(); i++) { Attribute tatt = (Attribute) tatts.get(i); - tvars.add(tatt.getName()); + if (tvars.contains(tatt.getName())) { } + else + { tvars.add(tatt.getName()); } } return tvars; } @@ -635,7 +683,9 @@ public Vector sourceVariables() Vector tvars = new Vector(); for (int i = 0; i < tatts.size(); i++) { Attribute tatt = (Attribute) tatts.get(i); - tvars.add(tatt.getName()); + if (tvars.contains(tatt.getName())) { } + else + { tvars.add(tatt.getName()); } } return tvars; } @@ -663,7 +713,9 @@ public Vector allVariables() Vector tvars = new Vector(); for (int i = 0; i < tatts.size(); i++) { Attribute tatt = (Attribute) tatts.get(i); - tvars.add(tatt.getName()); + if (tvars.contains(tatt.getName())) { } + else + { tvars.add(tatt.getName()); } } return tvars; } @@ -793,7 +845,7 @@ public Expression assertNotTraceRelation(Vector fparams, Vector entities) while (!(t.isEntity() && pivot.isSource())) { ind++; - if (ind > fparams.size()) + if (ind >= fparams.size()) { System.err.println("!!!! Error: no checkonly object domain for " + this); return pred; } @@ -1096,7 +1148,7 @@ public Vector toSourceExpression(Vector bound, Vector entities) return whencases; } */ - public Vector toGuardCondition(Vector bound, Vector entities) + public Vector toGuardCondition(Vector bound, Vector entities, Entity tr) { // for invoked rules only // b : T for each bound variable, and E->exists( e ... ) for other object variables @@ -1109,6 +1161,8 @@ public Vector toGuardCondition(Vector bound, Vector entities) Vector rootvariables = new Vector(); + // System.out.println("GUARD condition: " + whencases); + Vector newlist = new Vector(); for (int j = 0; j < whencases.size(); j++) { Expression ante = (Expression) whencases.get(j); @@ -1116,14 +1170,34 @@ public Vector toGuardCondition(Vector bound, Vector entities) for (int i = domain.size() - 1; i >= 0; i--) { Domain d = (Domain) domain.get(i); if (d.isCheckable) - { ex = d.toGuardCondition(rootvariables,ex); } + { ex = d.toGuardCondition(rootvariables,ex,tr); } } newlist.add(ex); } + // System.out.println("GUARD condition: " + newlist); + return newlist; } + public Expression undoExpression(Vector bound) + { // x /: y.r for each update x : y.r in an enforce domain + + Expression res = new BasicExpression(true); + + for (int i = 0; i < domain.size(); i++) + { Domain d = (Domain) domain.get(i); + if (d.isEnforceable) + { Expression ex = d.toUndoExpression(bound); + res = Expression.simplifyAnd(res,ex); + } + } + + System.out.println("Undo condition: " + res); + + return res; + } + /* public Expression toInverseSuccedent(Vector bound, Vector entities) { // for top-level rules only. Not used. @@ -1400,6 +1474,18 @@ public Vector toPreservationConstraints(UseCase uc, Vector entities, Vector type bound.addAll(allVariables()); Vector ante = toSourceExpressionOp(bound,entities); + Vector guards = toGuardCondition(bound,entities,ent); + + Constraint deleteTrace = deleteTraceConstraint(guards,ent,bound); + deleteTrace.setOwner(ent); + deleteTrace.setPrestate(true); + deleteTrace.setUseCase(uc); + Vector contexts = new Vector(); + contexts.add(ent); + contexts.addAll(entities); + deleteTrace.typeCheck(types,contexts,new Vector()); + res.add(deleteTrace); + Expression succ = toTargetExpressionPres(bound,uc,entities); // but no trace needed for (int i = 0; i < ante.size(); i++) { Expression antei = (Expression) ante.get(i); @@ -1553,4 +1639,25 @@ public static Expression deleteDomainExp(Attribute att) return new UnaryExpression("->isDeleted", arg); } + public Constraint deleteTraceConstraint(Vector preconds, Entity trent, Vector bound) + { Expression ante = new BasicExpression(true); + for (int i = 0; i < preconds.size(); i++) + { Expression precond = (Expression) preconds.get(i); + UnaryExpression notpre = new UnaryExpression("not",precond); + ante = Expression.simplifyAnd(ante,notpre); + } // set it to prestate. + + ante.setPre(); + + BasicExpression arg = new BasicExpression("self"); + arg.setUmlKind(Expression.VARIABLE); + arg.setType(new Type(trent)); + arg.setElementType(new Type(trent)); + arg.setEntity(trent); + + Expression succ = new UnaryExpression("->isDeleted", arg); + Expression undo = undoExpression(bound); + Expression succ1 = Expression.simplifyAnd(undo,succ); + return new Constraint(ante,succ1); + } } diff --git a/RelationDomain.java b/RelationDomain.java index bb39685c..d0290933 100644 --- a/RelationDomain.java +++ b/RelationDomain.java @@ -123,17 +123,23 @@ public Expression toSourceExpression(Vector bound) return res; } - public Expression toGuardCondition(Vector bound, Expression post) - { Expression contextObj = new BasicExpression(rootVariable); + public Expression toGuardCondition(Vector bound, Expression post, Entity tr) + { BasicExpression contextObj = new BasicExpression(rootVariable); + contextObj.setUmlKind(Expression.ROLE); + contextObj.setEntity(tr); // it is a property of the trace entity + // This should be bound, ie, in the call that is being guarded. if (isCheckable) { bound.add(rootVariable.getName()); } - Expression res = pattern.toGuardCondition(bound, contextObj, post); + Expression res = pattern.toGuardCondition(bound, contextObj, post, tr); + // res.setBrackets(true); + if (pattern != null && pattern.templateExpression != null && (pattern.templateExpression instanceof ObjectTemplateExp)) - { Expression btexp = new BasicExpression(rootVariable); + { BasicExpression btexp = new BasicExpression(rootVariable); + btexp.setUmlKind(Expression.ROLE); Expression scope = new BasicExpression(((ObjectTemplateExp) pattern.templateExpression).referredClass); Expression decl = new BinaryExpression(":", btexp, scope); @@ -148,6 +154,12 @@ public Expression toTargetExpression(Vector bound) return pattern.toTargetExpression(bound, contextObj, be); } + public Expression toUndoExpression(Vector bound) + { Expression contextObj = new BasicExpression(rootVariable); + BasicExpression be = new BasicExpression(true); + return pattern.toUndoExpression(bound, contextObj, be); + } + public Expression toSourceExpressionOp(Vector bound) { Expression contextObj = new BasicExpression(rootVariable); Expression res = pattern.toSourceExpression(bound, contextObj); diff --git a/RelationalTransformation.java b/RelationalTransformation.java index 18d49822..3eed770f 100644 --- a/RelationalTransformation.java +++ b/RelationalTransformation.java @@ -19,11 +19,18 @@ public class RelationalTransformation extends NamedElement { Vector modelParameter = new Vector(); // of TypedModel Vector rule = new Vector(); // of QVTRule Vector functions = new Vector(); // of BehaviouralFeature + String extending = null; public RelationalTransformation(String n) { super(n); } + public void setExtending(String ext) + { extending = ext; } + + public String getExtending() + { return extending; } + public int nops() { return functions.size(); } @@ -39,6 +46,45 @@ public void addRule(QVTRule r) public void addFunction(BehaviouralFeature bf) { functions.add(bf); } + public void union(RelationalTransformation tr) + { // Rules of tr are placed before rules of this, likewise for functions. + // Rules of tr with same name as element of rule are ignored, likewise for functions. + + Vector oldrules = new Vector(); // rules of tr not overriden + Vector newrules = new Vector(); // rules of this including overridding merges. + oldrules.addAll(tr.rule); + + for (int j = 0; j < rule.size(); j++) + { Relation rr = (Relation) rule.get(j); + Relation overriddenrule = (Relation) NamedElement.findByName(rr.getName(), tr.rule); + if (overriddenrule != null) // rule in both tr and this + { Relation newr = overriddenrule.overrideBy(rr); + newrules.add(newr); + oldrules.remove(overriddenrule); + } + else + { newrules.add(rr); } + } + + rule.clear(); + rule.addAll(oldrules); // inherited unchanged + rule.addAll(newrules); // new and overriding + + Vector newfunctions = new Vector(); + for (int i = 0; i < tr.functions.size(); i++) + { BehaviouralFeature rr = (BehaviouralFeature) tr.functions.get(i); + BehaviouralFeature overriderr = (BehaviouralFeature) + ModelElement.lookupByName(rr.getName(), functions); + if (overriderr != null) + { System.out.println(">>> new function " + rr.getName() + " overrides imported version"); } + else + { newfunctions.add(rr); } + } + newfunctions.addAll(functions); + functions.clear(); + functions.addAll(newfunctions); + } + public boolean typeCheck(Vector types, Vector entities, Vector contexts, Vector env) { for (int i = 0; i < functions.size(); i++) { BehaviouralFeature bf = (BehaviouralFeature) functions.get(i); @@ -161,26 +207,29 @@ public RelationalTransformation expandOverrides(Vector entities) { Relation rr = (Relation) r; if (rr.isConcrete() && rr.overrides()) { Relation newr = rr.flattenedRelation(rule); - System.out.println("******** New relation: "); + // System.out.println("******** New relation: "); System.out.println(newr); if (newr != null) { newrelations.add(newr); - Vector gc = newr.toGuardCondition(new Vector(),entities); - System.out.println(">>> Guard condition of " + newr.getName() + " is: " + gc); + Entity trent = (Entity) ModelElement.lookupByName(newr.getName() + "$trace", entities); + + Vector gc = newr.toGuardCondition(new Vector(),entities,trent); + // System.out.println(">>> Guard condition of " + newr.getName() + " is: " + gc); guardconditions.put(newr.getName(),gc); } } else if (rr.isConcrete()) { newrelations.add(rr); - Vector gc = rr.toGuardCondition(new Vector(),entities); - System.out.println(">>> Guard condition of " + rr.getName() + " is: " + gc); + Entity trent = (Entity) ModelElement.lookupByName(rr.getName() + "$trace", entities); + Vector gc = rr.toGuardCondition(new Vector(),entities,trent); + // System.out.println(">>> Guard condition of " + rr.getName() + " is: " + gc); guardconditions.put(rr.getName(),gc); } else { Vector leafs = rr.allLeafRelations(rule); abstractrelations.add(rr); leafrels.put(rr,leafs); - System.out.println(">>> All leaf relations of " + rr.getName() + " are: " + leafs); + // System.out.println(">>> All leaf relations of " + rr.getName() + " are: " + leafs); } } } @@ -301,6 +350,8 @@ public Constraint toCleanupConstraint(Entity e, Vector entities) } } + System.out.println(">>> All target trace features with type " + ename + " are: " + allArgs); + if (allArgs.size() == 0) { return null; } Attribute att = (Attribute) allArgs.get(0); @@ -312,8 +363,10 @@ public Constraint toCleanupConstraint(Entity e, Vector entities) } public String toString() - { String res = "transformation " + getName() + "\n" + - "{ "; + { String res = "transformation " + getName(); + if (extending != null) + { res = res + " extends " + extending; } + res = res + "\n" + "{ "; for (int i = 0; i < functions.size(); i++) { BehaviouralFeature f = (BehaviouralFeature) functions.get(i); diff --git a/SetExpression.java b/SetExpression.java index c9557e2b..cd27da61 100644 --- a/SetExpression.java +++ b/SetExpression.java @@ -27,7 +27,8 @@ public SetExpression(Vector v) elements.add(new BasicExpression(ss)); } } - } + } // For a map, the elements are BinaryExpressions representing pairs "," key value + public SetExpression(Vector v,boolean ord) { this(v); @@ -44,7 +45,7 @@ public int size() { return elements.size(); } public Expression definedness() - { Expression res = new BasicExpression("true"); // conjunction of definedness of elements + { Expression res = new BasicExpression(true); // conjunction of definedness of elements for (int i = 0; i < elements.size(); i++) { Expression elem = (Expression) elements.get(i); res = Expression.simplifyAnd(res,elem.definedness()); @@ -53,7 +54,7 @@ public Expression definedness() } public Expression determinate() - { Expression res = new BasicExpression("true"); // conjunction of definedness of elements + { Expression res = new BasicExpression(true); // conjunction of definedness of elements for (int i = 0; i < elements.size(); i++) { Expression elem = (Expression) elements.get(i); res = Expression.simplifyAnd(res,elem.determinate()); @@ -84,7 +85,23 @@ public Expression addPreForms(String var) Expression ne = elem.addPreForms(var); newelems.add(ne); } - return new SetExpression(newelems,ordered); + SetExpression result = new SetExpression(newelems,ordered); + result.setType(type); + result.setElementType(elementType); + return result; + } + + public Expression removePrestate() + { Vector newelems = new Vector(); + for (int i = 0; i < elements.size(); i++) + { Expression elem = (Expression) elements.get(i); + Expression ne = elem.removePrestate(); + newelems.add(ne); + } + Expression res = new SetExpression(newelems,ordered); + res.setType(type); + res.setElementType(elementType); + return res; } public void findClones(java.util.Map clones, String rule, String op) @@ -101,6 +118,9 @@ public boolean isOrdered() public boolean isOrderedB() { return ordered; } + + public boolean isMap() + { return type != null && "Map".equals(type.getName()); } public void setOrdered(boolean ord) { ordered = ord; } @@ -136,7 +156,10 @@ public void addElement(int i, Expression e) public String toString() { String res; - if (ordered) + + if (isMap()) + { res = "Map{"; } + else if (ordered) { res = "Sequence{"; } else { res = "Set{"; } @@ -195,7 +218,9 @@ public String saveModelData(PrintWriter out) public String toOcl(java.util.Map env, boolean local) { String res; - if (ordered) + if (isMap()) + { res = "Map{"; } + else if (ordered) { res = "Sequence{"; } else { res = "Set{"; } @@ -231,8 +256,22 @@ public boolean isPrimitive() public Expression skolemize(Expression sourceVar, java.util.Map env) { return this; } + /* TODO: add operations for MAPS. */ + public String queryForm(java.util.Map env, boolean local) - { String res = "(new SystemTypes.Set())"; + { if (isMap()) + { String result = "(new HashMap())"; + for (int i = 0; i < elements.size(); i++) + { BinaryExpression e = (BinaryExpression) elements.get(i); + Expression key = e.getLeft(); + Expression value = e.getRight(); + result = "Set.includingMap(" + result + "," + key.queryForm(env,local) + "," + + value.queryForm(env,local) + ")"; + } + return result; + } + + String res = "(new SystemTypes.Set())"; for (int i = 0; i < elements.size(); i++) { Expression e = (Expression) elements.get(i); res = res + ".add(" + wrap(elementType, e.queryForm(env,local)) + ")"; @@ -242,7 +281,19 @@ public String queryForm(java.util.Map env, boolean local) } // different for sequences? public String queryFormJava6(java.util.Map env, boolean local) - { String res = "(new HashSet())"; + { if (isMap()) + { String result = "(new HashMap())"; + for (int i = 0; i < elements.size(); i++) + { BinaryExpression e = (BinaryExpression) elements.get(i); + Expression key = e.getLeft(); + Expression value = e.getRight(); + result = "Set.includingMap(" + result + "," + key.queryFormJava6(env,local) + "," + + value.queryFormJava6(env,local) + ")"; + } + return result; + } + + String res = "(new HashSet())"; if (ordered) { res = "(new ArrayList())"; } @@ -258,7 +309,21 @@ public String queryFormJava6(java.util.Map env, boolean local) } // different for sequences? public String queryFormJava7(java.util.Map env, boolean local) - { if (type == null) + { + if (isMap()) + { String mtype = type.getJava7(elementType); + String result = "(new " + mtype + "())"; + for (int i = 0; i < elements.size(); i++) + { BinaryExpression e = (BinaryExpression) elements.get(i); + Expression key = e.getLeft(); + Expression value = e.getRight(); + result = "Ocl.includingMap(" + result + "," + key.queryFormJava7(env,local) + "," + + value.queryFormJava7(env,local) + ")"; + } + return result; + } + + if (type == null) { if (ordered) { type = new Type("Sequence",null); } else @@ -283,14 +348,26 @@ public String queryFormJava7(java.util.Map env, boolean local) } // different for sequences? public String queryFormCSharp(java.util.Map env, boolean local) - { String res = "(new ArrayList())"; + { if (isMap()) + { String result = "(new Hashtable())"; + for (int i = 0; i < elements.size(); i++) + { BinaryExpression e = (BinaryExpression) elements.get(i); + Expression key = e.getLeft(); + Expression value = e.getRight(); + result = "System.includingMap(" + result + "," + key.queryFormCSharp(env,local) + "," + + value.queryFormCSharp(env,local) + ")"; + } + return result; + } + + String res = "(new ArrayList())"; for (int i = 0; i < elements.size(); i++) { Expression e = (Expression) elements.get(i); res = "SystemTypes.addSet(" + res + "," + Expression.wrapCSharp(elementType, e.queryFormCSharp(env,local)) + ")"; } return res; - } // different for sequences? + } public String queryFormCPP(java.util.Map env, boolean local) { Type et = getElementType(); @@ -298,7 +375,19 @@ public String queryFormCPP(java.util.Map env, boolean local) if (et != null) { cet = et.getCPP(et.getElementType()); } - String collkind = "Set"; + if (isMap()) + { String result = "(new map())"; + for (int i = 0; i < elements.size(); i++) + { BinaryExpression e = (BinaryExpression) elements.get(i); + Expression key = e.getLeft(); + Expression value = e.getRight(); + result = "UmlRsdsLib<" + cet + ">::includingMap(" + result + "," + key.queryFormCPP(env,local) + "," + + value.queryFormCPP(env,local) + ")"; + } + return result; + } + + String collkind = "Set"; String res = "(new set<" + cet + ">())"; if (ordered) { res = "(new vector<" + cet + ">())"; @@ -334,7 +423,7 @@ public BExpression bqueryForm(java.util.Map env) } return new BSetExpression(elems,ordered); - } + } // maps? public BExpression bqueryForm() { Vector elems = new Vector(); @@ -357,7 +446,7 @@ public BExpression bqueryForm() } return new BSetExpression(elems,ordered); - } + } // maps? public int minModality() { int mm = 9; @@ -522,7 +611,9 @@ else if (eent != null && Entity.isAncestor(eent,entity)) } // deduce element type and type itself, and the entity?? - if (ordered) + if (isMap()) + { type = new Type("Map", null); } + else if (ordered) { type = new Type("Sequence",null); } else { type = new Type("Set",null); } @@ -565,6 +656,15 @@ public Vector allEntitiesUsedIn() return res; } + public Vector allAttributesUsedIn() + { Vector res = new Vector(); + for (int i = 0; i < elements.size(); i++) + { Expression val = (Expression) elements.get(i); + res = VectorUtil.union(res,val.allAttributesUsedIn()); + } + return res; + } + public boolean relevantOccurrence(String op, Entity ent, String f, String val) { return false; } @@ -631,7 +731,10 @@ public Expression substitute(Expression old, Expression be = e.substitute(old,n); elems.add(be); } - return new SetExpression(elems,ordered); + SetExpression result = new SetExpression(elems,ordered); + if (isMap()) + { result.setType(type); } + return result; } public Expression substituteEq(String old, @@ -642,7 +745,10 @@ public Expression substituteEq(String old, Expression be = e.substituteEq(old,n); elems.add(be); } - return new SetExpression(elems,ordered); + SetExpression result = new SetExpression(elems,ordered); + if (isMap()) + { result.setType(type); } + return result; } public boolean isOrExpression() { return false; } @@ -658,7 +764,7 @@ public String toJava() res = res + ".add(" + val + ")"; } return res + ".getElements()"; - } // ordered? + } // ordered? Maps? public String toB() { return ""; } @@ -719,7 +825,10 @@ public Expression simplify(final Vector vars) Expression newval = val.simplify(vars); newvals.add(newval); } - return new SetExpression(newvals,ordered); + SetExpression result = new SetExpression(newvals,ordered); + if (isMap()) + { result.setType(type); } + return result; } // could eliminate duplicates public Expression simplify() @@ -729,7 +838,10 @@ public Expression simplify() Expression newval = val.simplify(); newvals.add(newval); } - return new SetExpression(newvals,ordered); + SetExpression result = new SetExpression(newvals,ordered); + if (isMap()) + { result.setType(type); } + return result; } // could eliminate duplicates for ordered == false public Expression filter(final Vector vars) @@ -811,6 +923,7 @@ public Expression dereference(BasicExpression ref) } SetExpression res = new SetExpression(newelems); res.ordered = ordered; + res.type = type; return res; } @@ -822,7 +935,8 @@ public Expression addReference(BasicExpression ref, Type t) newelems.add(newelem); } SetExpression res = new SetExpression(newelems); - res.ordered = ordered; + res.ordered = ordered; + res.type = type; return res; } @@ -834,7 +948,8 @@ public Expression replaceReference(BasicExpression ref, Type t) newelems.add(newelem); } SetExpression res = new SetExpression(newelems); - res.ordered = ordered; + res.ordered = ordered; + res.type = type; return res; } @@ -878,10 +993,15 @@ public String cg(CGSpec cgs) } args.add(arg); CGRule r = cgs.matchedSetExpressionRule(this,etext); - System.out.println(">> Found rule " + r); if (r != null) - { return r.applyRule(args); } + { System.out.println(">> Found rule " + r + " for: " + etext); + String res = r.applyRule(args); + if (needsBracket) + { return "(" + res + ")"; } + else + { return res; } + } return etext; } diff --git a/Statement.java b/Statement.java index 40820a99..bfbe49e3 100644 --- a/Statement.java +++ b/Statement.java @@ -35,9 +35,9 @@ public void setBrackets(boolean b) abstract String getOperator(); public String cg(CGSpec cgs) - { String etext = this + ""; - return etext; - } + { return this + ""; } + + public abstract Vector metavariables(); abstract String bupdateForm(); @@ -441,6 +441,8 @@ public static Statement combineIfStatements(Statement s1, Statement s2) abstract public Vector allOperationsUsedIn(); abstract public Vector equivalentsUsedIn(); + + abstract public String toEtl(); } @@ -459,6 +461,9 @@ public String getOperator() public Object clone() { return new ReturnStatement(value); } + public boolean hasValue() + { return value != null; } + public void display() { System.out.print(" return"); if (value != null) @@ -527,6 +532,14 @@ public String toStringJava() return res; } + public String toEtl() + { String res = " return"; + if (value != null) + { res = res + " " + value; } + res = res + ";"; + return res; + } + public boolean typeCheck(Vector types, Vector entities, Vector ctxs, Vector env) { if (value == null) { return true; } return value.typeCheck(types,entities,ctxs,env); @@ -606,6 +619,13 @@ public Statement dereference(BasicExpression var) return new ReturnStatement(val); } + public Vector metavariables() + { Vector res = new Vector(); + if (value != null) + { return value.metavariables(); } + return res; + } + public Vector readFrame() { Vector res = new Vector(); if (value == null) @@ -657,6 +677,17 @@ public Vector equivalentsUsedIn() { return res; } return value.equivalentsUsedIn(); } + + public String cg(CGSpec cgs) + { String etext = this + ""; + Vector args = new Vector(); + if (value != null) + { args.add(value.cg(cgs)); } + CGRule r = cgs.matchedStatementRule(this,etext); + if (r != null) + { return r.applyRule(args); } + return etext; + } } @@ -693,6 +724,9 @@ public Statement substituteEq(String oldE, Expression newE) public String toStringJava() { return " break;"; } + public String toEtl() + { return " break;"; } + public String saveModelData(PrintWriter out) { String res = Identifier.nextIdentifier("breakstatement_"); out.println(res + " : BreakStatement"); @@ -765,6 +799,20 @@ public Vector equivalentsUsedIn() { Vector res = new Vector(); return res; } + + public Vector metavariables() + { Vector res = new Vector(); + return res; + } + + public String cg(CGSpec cgs) + { String etext = this + ""; + Vector args = new Vector(); + CGRule r = cgs.matchedStatementRule(this,etext); + if (r != null) + { return r.applyRule(args); } + return etext; + } } @@ -960,6 +1008,15 @@ public String toStringJava(String targ) } + public String toEtl() + { String res = ""; + if (assignsTo != null) + { res = assignsTo + " = "; } + res = res + action + ";"; + return res; + } + + public void display() { System.out.print(toString()); @@ -1254,6 +1311,37 @@ public Vector equivalentsUsedIn() { return res; } return callExp.equivalentsUsedIn(); } + + public Vector metavariables() + { Vector res = new Vector(); + if (callExp != null) + { return callExp.metavariables(); } + return res; + } + + public String cg(CGSpec cgs) + { String etext = this + ""; + Vector args = new Vector(); + if (callExp != null) + { args.add(callExp.cg(cgs)); } + CGRule r = cgs.matchedStatementRule(this,etext); + if (r != null) + { return r.applyRule(args); } + else + { r = cgs.matchedTextRule(etext); + if (r != null) + return r.applyTextRule(etext); + } + return etext; + } + + public Vector cgparameters() + { Vector args = new Vector(); + if (callExp != null) + { args.add(callExp); } + return args; + } + } @@ -1342,6 +1430,12 @@ public String toStringJava() return res; } + public String toEtl() + { String res = " " + callExp + ";"; + return res; + } + + public String toStringJava(String targ) { return toStringJava(); } @@ -1500,6 +1594,30 @@ public Vector equivalentsUsedIn() return callExp.equivalentsUsedIn(); } + public Vector metavariables() + { Vector res = new Vector(); + if (callExp != null) + { return callExp.metavariables(); } + return res; + } + + public String cg(CGSpec cgs) + { String etext = this + ""; + Vector args = new Vector(); + if (callExp != null) + { args.add(callExp.cg(cgs)); } + CGRule r = cgs.matchedStatementRule(this,etext); + if (r != null) + { return r.applyRule(args); } + return etext; + } + + public Vector cgparameters() + { Vector args = new Vector(); + if (callExp != null) + { args.add(callExp); } + return args; + } } @@ -1623,7 +1741,7 @@ public void setVariant(Expression inv) { variant = inv; } public static WhileStatement createInvocationLoop(BasicExpression call, Expression range) - { String v = Identifier.nextIdentifier("loopvar_"); + { String v = Identifier.nextIdentifier("loopvar$"); BasicExpression ve = new BasicExpression(v); Type elemt = range.getElementType(); @@ -1744,11 +1862,11 @@ public BStatement bupdateForm(java.util.Map env, boolean local) if (variant != null) { bvar = variant.binvariantForm(env,local); } - System.out.println("LOOP BODY = " + body); + // System.out.println("LOOP BODY = " + body); BStatement bbody = body.bupdateForm(env,local); - System.out.println("LOOP BODY = " + bbody); + // System.out.println("LOOP BODY = " + bbody); return new BLoopStatement(btest,binv,bvar,bbody); } @@ -1932,6 +2050,17 @@ public String toStringJava() return res + " }"; } + public String toEtl() + { String loop = "while"; + if (loopKind == FOR) + { loop = "for"; } + + String res = " " + loop + " (" + loopTest + ")"; + res = res + " {\n "; + res = res + body.toEtl(); + return res + " }"; + } + public String toString() { String res = " while "; if (loopKind == FOR) @@ -1980,6 +2109,18 @@ public boolean updates(Vector v) public Statement generateDesign(java.util.Map env, boolean local) { Statement bdy = body.generateDesign(env,local); WhileStatement result = (WhileStatement) clone(); + if (loopRange != null && loopRange instanceof BasicExpression) + { if (loopRange.umlkind == Expression.CLASSID) + { BasicExpression lr = new BasicExpression("allInstances"); + lr.umlkind = Expression.FUNCTION; + lr.setIsEvent(); + lr.setParameters(null); + lr.type = loopRange.type; + lr.elementType = loopRange.elementType; + lr.setObjectRef(loopRange); + result.loopRange = lr; + } + } result.body = bdy; return result; } @@ -2523,23 +2664,43 @@ public Vector equivalentsUsedIn() public String cg(CGSpec cgs) { String etext = this + ""; + + Vector eargs = new Vector(); Vector args = new Vector(); if (loopKind == WHILE) { args.add(loopTest.cg(cgs)); args.add(body.cg(cgs)); + eargs.add(loopTest); + eargs.add(body); } else - { args.add(loopVar); + { args.add(loopVar + ""); args.add(loopRange.cg(cgs)); args.add(body.cg(cgs)); + eargs.add(loopVar); + eargs.add(loopRange); + eargs.add(body); } CGRule r = cgs.matchedStatementRule(this,etext); if (r != null) - { return r.applyRule(args); } + { return r.applyRule(args,eargs,cgs); } return etext; } // for FOR, need the loopVar : loopRange // instead of test. + public Vector metavariables() + { Vector res = new Vector(); + if (loopKind == WHILE && loopTest != null) + { res.addAll(loopTest.metavariables()); } + else if (loopVar != null && loopRange != null) + { res.addAll(loopVar.metavariables()); + res.addAll(loopRange.metavariables()); + } + res = VectorUtil.union(res,body.metavariables()); + return res; + } + + } @@ -2549,16 +2710,20 @@ class CreationStatement extends Statement private Type instanceType = null; private Type elementType = null; boolean declarationOnly = false; + String initialValue = null; public CreationStatement(String cio, String ast) { createsInstanceOf = cio; assignsTo = ast; } + public void setInitialValue(String init) + { initialValue = init; } + public String getOperator() { return "var"; } - public String cg(CGSpec cgs) +/* public String cg(CGSpec cgs) { String etext = "var " + assignsTo + " : " + createsInstanceOf; Vector args = new Vector(); args.add(assignsTo); @@ -2567,7 +2732,7 @@ public String cg(CGSpec cgs) if (r != null) { return r.applyRule(args); } return etext; - } + } */ public void setInstanceType(Type t) { instanceType = t; @@ -2609,7 +2774,11 @@ public Statement substituteEq(String oldE, Expression newE) } public String toString() - { return assignsTo + " : " + createsInstanceOf; } + { if (initialValue != null) + { return " var " + assignsTo + " = " + initialValue; } + else + { return assignsTo + " : " + createsInstanceOf; } + } public String saveModelData(PrintWriter out) { String res = Identifier.nextIdentifier("creationstatement_"); @@ -2648,8 +2817,17 @@ public BStatement bupdateForm(java.util.Map env, boolean local) return new BAnyStatement(updates, bqual, new BBasicStatement("skip")); } // No - add to the entity involved. + public String toEtl() + { if (initialValue != null) + { return " var " + assignsTo + " = " + initialValue + ";"; } + else + { return " var " + assignsTo + ";"; } + } + public String toStringJava() - { if (instanceType != null) + { if (initialValue != null) + { return " var " + assignsTo + " = " + initialValue; } + else if (instanceType != null) { String jType = instanceType.getJava(); if (Type.isBasicType(instanceType)) { return " " + jType + " " + assignsTo + ";"; } @@ -2794,11 +2972,12 @@ else if (Type.isCollectionType(instanceType)) { return " " + jType + " " + assignsTo + ";"; } else if (instanceType.isEntity()) { Entity ent = instanceType.getEntity(); + String ename = ent.getName(); if (ent.hasStereotype("external")) - { return " " + jType + " " + assignsTo + " = new " + jType + "();\n"; } + { return " " + jType + " " + assignsTo + " = new " + ename + "();\n"; } else - { return " " + jType + " " + assignsTo + " = new " + jType + "();\n" + - " Controller::inst->add" + jType + "(" + assignsTo + ");"; + { return " " + jType + " " + assignsTo + " = new " + ename + "();\n" + + " Controller::inst->add" + ename + "(" + assignsTo + ");"; } } } @@ -2921,6 +3100,49 @@ public Vector equivalentsUsedIn() { Vector res = new Vector(); return res; } + + public Vector metavariables() + { Vector res = new Vector(); + if (assignsTo != null) + { if (assignsTo.startsWith("_")) + { res.add(assignsTo); } + } + + if (instanceType != null) + { res.addAll(instanceType.metavariables()); } + return res; + } + + public Vector cgparameters() + { Vector args = new Vector(); + if (assignsTo != null) + { args.add(assignsTo); } + if (instanceType != null) + { args.add(instanceType); } + return args; + } + + + public String cg(CGSpec cgs) + { String etext = this + ""; + Vector args = new Vector(); + Vector eargs = new Vector(); + + if (assignsTo != null) + { args.add(assignsTo); + eargs.add(assignsTo); + } + + if (instanceType != null) + { args.add(instanceType.cg(cgs)); + eargs.add(instanceType); + } + + CGRule r = cgs.matchedStatementRule(this,etext); + if (r != null) + { return r.applyRule(args,eargs,cgs); } + return etext; + } } @@ -2951,7 +3173,9 @@ public String cg(CGSpec cgs) { String etext = this + ""; Vector args = new Vector(); if (statements.size() == 0) - { etext = "skip"; } + { etext = "skip"; + return ""; + } else if (statements.size() == 1) { Statement st = (Statement) statements.get(0); return st.cg(cgs); @@ -2968,7 +3192,12 @@ else if (statements.size() == 1) } CGRule r = cgs.matchedStatementRule(this,etext); if (r != null) - { return r.applyRule(args); } + { // System.out.println(">>> Sequence rule: " + r + + // " " + args); + String res = r.applyRule(args); + // System.out.println(">>> Applied sequence rule: " + res); + return res; + } return etext; } @@ -3218,6 +3447,21 @@ public String toStringJava() return res; } + public String toEtl() + { String res = ""; + for (int i = 0; i < statements.size(); i++) + { Statement ss = (Statement) statements.elementAt(i); + if (i > 0) /* Hack */ + { res = res + " "; } + if (ss != null) + { res = res + ss.toEtl(); } + res = res + "\n"; + } + // if (brackets) + // { res = "( " + res + " )"; } + return res; + } + public String toString() { String res = ""; for (int i = 0; i < statements.size(); i++) @@ -3508,6 +3752,15 @@ public Vector equivalentsUsedIn() return res; } + public Vector metavariables() + { Vector res = new Vector(); + for (int i = 0; i < statements.size(); i++) + { Statement stat = (Statement) statements.get(i); + { res.addAll(stat.metavariables()); } + } + + return res; + } } @@ -3736,6 +3989,25 @@ public String toStringJava() return res; } + public String toEtl() + /* s is name of actuator/sensor */ + { int n = cases.elements.size(); + String res = ""; + String s = "s"; + + for (int i = 0; i < n; i++) + { Maplet mm = (Maplet) cases.elements.elementAt(i); + res = res + " if (M" + s + "." + s + " == " + + ((Named) mm.source).label + ")"; + res = res + " {\n"; + res = res + ((Statement) mm.dest).toEtl(); + res = res + " }\n"; + if (i < n-1) + { res = res + " else {\n"; } + } + return res; + } + public boolean typeCheck(Vector types, Vector entities, Vector cs, Vector env) { return true; } // type check each case dest? @@ -3836,6 +4108,14 @@ public Vector equivalentsUsedIn() return res; } + public Vector metavariables() + { Vector res = new Vector(); + for (int i = 0; i < cases.elements.size(); i++) + { Maplet mm = (Maplet) cases.elements.get(i); + res.addAll(((Statement) mm.dest).metavariables()); + } + return res; + } } @@ -3880,6 +4160,9 @@ public String saveModelData(PrintWriter out) public String toStringJava() { return " {} /* Unreachable state */"; } + public String toEtl() + { return ""; } + public void displayJava(String t, PrintWriter out) { out.println(" {} /* Unreachable state */"); } @@ -3946,6 +4229,10 @@ public Vector equivalentsUsedIn() return res; } + public Vector metavariables() + { Vector res = new Vector(); + return res; + } } @@ -4277,6 +4564,27 @@ public String toStringJava() return res; } + public String toEtl() + { String res = ""; + int n = cases.size(); + if (n == 0) + { return res; } + + for (int j = 0; j < n; j++) + { IfCase ic = (IfCase) cases.elementAt(j); + Expression test = ic.getTest(); + Statement stat = ic.getIf(); + if ("true".equals(test + "")) + { res = res + stat; } + else + { res = res + " if (" + test + ") { " + stat.toEtl() + " }\n"; + if (j < n-1) + { res = res + " else "; } + } + } + return res; + } + public String toString() { int n = cases.size(); String res = ""; @@ -4650,11 +4958,51 @@ public Vector equivalentsUsedIn() return res; } + public Vector metavariables() + { Vector res = new Vector(); + for (int i = 0; i < cases.size(); i++) + { IfCase ic = (IfCase) cases.get(i); + res.addAll(ic.metavariables()); + } + return res; + } + + public String cg(CGSpec cgs) + { String etext = this + ""; + Vector args = new Vector(); + + if (cases.size() > 0) + { IfCase ic1 = (IfCase) cases.get(0); + Expression test1 = ic1.getTest(); + if ("true".equals(test1 + "")) + { Statement stat1 = ic1.getIf(); + return stat1.cg(cgs); + } + } + + if (cases.size() > 0) + { IfCase ic1 = (IfCase) cases.get(0); + args.add(ic1.getTest().cg(cgs)); + args.add(ic1.getIf().cg(cgs)); + } + + if (cases.size() > 1) // if then else + { IfCase ic2 = (IfCase) cases.get(1); + args.add(ic2.getIf().cg(cgs)); + } + else // if then + { args.add(""); } + + CGRule r = cgs.matchedStatementRule(this,etext); + if (r != null) + { return r.applyRule(args); } + return etext; + } } class AssignStatement extends Statement -{ private Type type; // for declarations +{ private Type type = null; // for declarations private Expression lhs; private Expression rhs; private boolean copyValue = false; @@ -4665,9 +5013,28 @@ public AssignStatement(Expression left, Expression right) rhs = right; } + public AssignStatement(Attribute left, Expression right) + { lhs = new BasicExpression(left); + rhs = right; + } + + public AssignStatement(Binding b) + { lhs = new BasicExpression(b.getPropertyName()); + rhs = b.expression; + } + + public AssignStatement(String left, Expression right) + { lhs = new BasicExpression(left); + rhs = right; + } + public String getOperator() { return ":="; } + public Expression getLeft() + { return lhs; } + + public void setType(Type t) { type = t; } @@ -4676,14 +5043,59 @@ public void setElementType(Type t) // rhs.elementType = t; } + public Vector cgparameters() + { Vector args = new Vector(); + args.add(lhs); + args.add(rhs); + return args; + } + + + public String basiccg(CGSpec cgs) + { // assumes type == null + String etext = this + ""; + Vector args = new Vector(); + args.add(lhs.cg(cgs)); + Vector eargs = new Vector(); + eargs.add(lhs); + Expression rhsnopre = rhs.removePrestate(); + args.add(rhsnopre.cg(cgs)); + eargs.add(rhsnopre); + + CGRule r = cgs.matchedStatementRule(this,etext); + if (r != null) + { return r.applyRule(args,eargs,cgs); } + return etext; + } + + + public String cg(CGSpec cgs) - { String etext = this + ""; + { if (type != null) + { // process as var lhs : type ; lhs := rhs; + SequenceStatement stat = new SequenceStatement(); + CreationStatement cre = new CreationStatement(type + "", lhs + ""); + cre.setType(type); + cre.setElementType(lhs.elementType); + AssignStatement newas = new AssignStatement(lhs,rhs); + newas.type = null; + stat.addStatement(cre); + stat.addStatement(newas); + return stat.cg(cgs); + } + + String etext = this + ""; Vector args = new Vector(); args.add(lhs.cg(cgs)); - args.add(rhs.cg(cgs)); + Vector eargs = new Vector(); + eargs.add(lhs); + Expression rhsnopre = rhs.removePrestate(); + args.add(rhsnopre.cg(cgs)); + eargs.add(rhsnopre); + CGRule r = cgs.matchedStatementRule(this,etext); if (r != null) - { return r.applyRule(args); } + { return r.applyRule(args,eargs,cgs); } return etext; } @@ -4794,6 +5206,11 @@ public String toStringJava() return res; } + public String toEtl() + { String res = lhs + " = " + rhs + ";"; + return res; + } + // public String toString() // { return lhs + " := " + rhs + " "; } @@ -5098,6 +5515,11 @@ public Vector equivalentsUsedIn() return res; } + public Vector metavariables() + { Vector res = lhs.metavariables(); + res.addAll(rhs.metavariables()); + return res; + } } @@ -5212,6 +5634,12 @@ public String toStringJava() return res + " }\n"; } + public String toEtl() + { String res = "if (" + test + ") { "; + res = res + ifPart.toEtl(); + return res + " }\n"; + } + public boolean typeCheck(Vector types, Vector entities, Vector cs, Vector env) { boolean res1 = test.typeCheck(types,entities,cs,env); boolean res2 = ifPart.typeCheck(types,entities,cs,env); @@ -5355,6 +5783,12 @@ public Vector equivalentsUsedIn() res.addAll(ifPart.equivalentsUsedIn()); return res; } + + public Vector metavariables() + { Vector res = test.metavariables(); + res.addAll(ifPart.metavariables()); + return res; + } } @@ -5375,15 +5809,27 @@ class ConditionalStatement extends Statement elsePart = s2; } + public void setElse(Statement stat) + { elsePart = stat; } + public String getOperator() { return "if"; } + public Expression getTest() + { return test; } + public String cg(CGSpec cgs) { String etext = this + ""; Vector args = new Vector(); + + if ("true".equals(test + "")) + { return ifPart.cg(cgs); } + args.add(test.cg(cgs)); args.add(ifPart.cg(cgs)); - args.add(elsePart.cg(cgs)); + if (elsePart == null) + { elsePart = new SequenceStatement(); } + args.add(elsePart.cg(cgs)); CGRule r = cgs.matchedStatementRule(this,etext); if (r != null) @@ -5401,7 +5847,9 @@ public Object clone() } public Statement generateDesign(java.util.Map env, boolean local) - { Statement ifc = ifPart.generateDesign(env,local); + { Statement ifc = ifPart.generateDesign(env,local); + if ("true".equals(test + "")) + { return ifc; } Statement elsec = null; if (elsePart != null) { elsec = elsePart.generateDesign(env,local); } @@ -5416,9 +5864,16 @@ public String toString() } public String toStringJava() - { String res = "if " + test + " then " + ifPart; + { String res = "if (" + test + ") { " + ifPart + " } "; if (elsePart != null) - { res = res + " else " + elsePart; } + { res = res + " else { " + elsePart + " }"; } + return res; + } + + public String toEtl() + { String res = " if (" + test + ") { " + ifPart.toEtl() + " }\n"; + if (elsePart != null) + { res = res + " else { " + elsePart.toEtl() + " }"; } return res; } @@ -5437,16 +5892,18 @@ public void display() } public void displayJava(String v, java.io.PrintWriter out) - { String res = "if " + test + " then " + ifPart; + { out.println(" if (" + test + ")"); + out.println(" { " + ifPart + " }"); if (elsePart != null) - { res = res + " else " + elsePart; } - out.println(res); + { out.println(" else "); + out.println(" { " + elsePart + " }"); + } } public void displayJava(String v) - { String res = "if " + test + " then " + ifPart; + { String res = "if (" + test + ") { " + ifPart + " }"; if (elsePart != null) - { res = res + " else " + elsePart; } + { res = res + " else { " + elsePart + " }"; } System.out.println(res); } @@ -5492,7 +5949,14 @@ public boolean typeCheck(Vector types, Vector entities, Vector cs, Vector env) } public Expression wpc(Expression post) - { return new BinaryExpression("=>", test, ifPart.wpc(post)); } + { BinaryExpression ifimpl = new BinaryExpression("=>", test, ifPart.wpc(post)); + if (elsePart != null) + { UnaryExpression ntest = new UnaryExpression("not", test); + BinaryExpression elseimpl = new BinaryExpression("=>", ntest, elsePart.wpc(post)); + return new BinaryExpression("&", ifimpl, elseimpl); + } + return ifimpl; + } // and else if present public Vector dataDependents(Vector allvars, Vector vars) @@ -5509,15 +5973,21 @@ else if (elsePart != null && elsePart.updates(v)) public String updateForm(java.util.Map env, boolean local, Vector types, Vector entities, Vector vars) - { String res = "if " + test.queryForm(env,local) + "\n"; - res = res + "{ " + ifPart.updateForm(env,local,types,entities,vars) + " }\n"; + { if ("true".equals(test + "")) + { return " { " + ifPart.updateForm(env,local,types,entities,vars) + " }\n"; } + + String res = " if (" + test.queryForm(env,local) + ")\n"; + res = res + " { " + ifPart.updateForm(env,local,types,entities,vars) + " }\n"; if (elsePart != null) - { res = res + "else { " + elsePart.updateForm(env,local,types,entities,vars) + " }\n"; } + { res = res + " else { " + elsePart.updateForm(env,local,types,entities,vars) + " }\n"; } return res; } public String updateFormJava6(java.util.Map env, boolean local) - { String res = "if " + test.queryFormJava6(env,local) + "\n"; + { if ("true".equals(test + "")) + { return " { " + ifPart.updateFormJava6(env,local) + " }\n"; } + + String res = "if (" + test.queryFormJava6(env,local) + ")\n"; res = res + "{ " + ifPart.updateFormJava6(env,local) + " }\n"; if (elsePart != null) { res = res + "else { " + elsePart.updateFormJava6(env,local) + " }\n"; } @@ -5525,7 +5995,10 @@ public String updateFormJava6(java.util.Map env, boolean local) } public String updateFormJava7(java.util.Map env, boolean local) - { String res = "if " + test.queryFormJava7(env,local) + "\n"; + { if ("true".equals(test + "")) + { return " { " + ifPart.updateFormJava7(env,local) + " }\n"; } + + String res = "if (" + test.queryFormJava7(env,local) + ")\n"; res = res + "{ " + ifPart.updateFormJava7(env,local) + " }\n"; if (elsePart != null) { res = res + "else { " + elsePart.updateFormJava7(env,local) + " }\n"; } @@ -5533,7 +6006,10 @@ public String updateFormJava7(java.util.Map env, boolean local) } public String updateFormCSharp(java.util.Map env, boolean local) - { String res = "if " + test.queryFormCSharp(env,local) + "\n"; + { if ("true".equals(test + "")) + { return " { " + ifPart.updateFormCSharp(env,local) + " }\n"; } + + String res = "if (" + test.queryFormCSharp(env,local) + ")\n"; res = res + "{ " + ifPart.updateFormCSharp(env,local) + " }\n"; if (elsePart != null) { res = res + "else { " + elsePart.updateFormCSharp(env,local) + " }\n"; } @@ -5541,7 +6017,10 @@ public String updateFormCSharp(java.util.Map env, boolean local) } public String updateFormCPP(java.util.Map env, boolean local) - { String res = "if " + test.queryFormCPP(env,local) + "\n"; + { if ("true".equals(test + "")) + { return " { " + ifPart.updateFormCPP(env,local) + " }\n"; } + + String res = "if (" + test.queryFormCPP(env,local) + ")\n"; res = res + "{ " + ifPart.updateFormCPP(env,local) + " }\n"; if (elsePart != null) { res = res + "else { " + elsePart.updateFormCPP(env,local) + " }\n"; } @@ -5664,5 +6143,12 @@ public Vector equivalentsUsedIn() return res; } + public Vector metavariables() + { Vector res = test.metavariables(); + res.addAll(ifPart.metavariables()); + if (elsePart != null) + { res.addAll(elsePart.metavariables()); } + return res; + } } diff --git a/SystemTypes.java b/SystemTypes.java index 97a0f7bc..3cf2c84c 100644 --- a/SystemTypes.java +++ b/SystemTypes.java @@ -348,9 +348,11 @@ static List mergeSort(final List a, java.util.Map f, int ind1, int ind2) { Comparable e1 = (Comparable) f.get(a.get(ind1)); Comparable e2 = (Comparable) f.get(a.get(ind2)); if (e1.compareTo(e2) < 0) // e1 < e2 - { res.add(a.get(ind1)); res.add(a.get(ind2)); return res; } + { res.add(a.get(ind1)); res.add(a.get(ind2)); + return res; } else - { res.add(a.get(ind2)); res.add(a.get(ind1)); return res; } + { res.add(a.get(ind2)); res.add(a.get(ind1)); + return res; } } int mid = (ind1 + ind2)/2; List a1; @@ -362,8 +364,11 @@ static List mergeSort(final List a, java.util.Map f, int ind1, int ind2) } else { a1 = mergeSort(a,f,ind1,mid-1); + System.out.println(">>> merge sorted " + a + " with " + f + " from " + ind1 + " to " + (mid -1) + ": " + a1); a2 = mergeSort(a,f,mid,ind2); + System.out.println(">>> merge sorted " + a + " with " + f + " from " + mid + " to " + (ind2) + ": " + a2); } + int i = 0; int j = 0; while (i < a1.size() && j < a2.size()) @@ -756,5 +761,6 @@ public static Map intersectionMap(Map m1, Map m2) return res; } + } } diff --git a/TemplateExp.java b/TemplateExp.java index 9aa0c9fb..06967931 100644 --- a/TemplateExp.java +++ b/TemplateExp.java @@ -21,12 +21,15 @@ public TemplateExp(Attribute v, Expression e) public abstract boolean typeCheck(Vector types, Vector entities, Vector contexts, Vector env); - public abstract Expression toGuardCondition(Vector bound, Expression contextObj, Expression post); + public abstract Expression toGuardCondition(Vector bound, Expression contextObj, Expression post, + Entity tr); public abstract Expression toSourceExpression(Vector bound, Expression contextObj); public abstract Expression toTargetExpression(Vector bound, Expression contextObj, Expression setting); + public abstract Expression toUndoExpression(Vector bound, Expression contextObj, Expression setting); + public abstract Expression toTargetExpressionOp(Vector bound, Expression contextObj, Expression setting); public abstract Vector getObjectTemplateAttributes(Vector vars); diff --git a/Thesarus.java b/Thesarus.java index af3c07ce..c1892179 100644 --- a/Thesarus.java +++ b/Thesarus.java @@ -44,7 +44,7 @@ public boolean hasTerm(String t) { boolean res = false; for (int i = 0; i < terms.size(); i++) { ThesaurusTerm tt = (ThesaurusTerm) terms.get(i); - if (t.equals(tt.name)) + if (t.equalsIgnoreCase(tt.name)) { return true; } } return res; @@ -54,7 +54,7 @@ public boolean hasPreferredTerm(String t) { boolean res = false; for (int i = 0; i < preferredTerms.size(); i++) { ThesaurusTerm tt = (ThesaurusTerm) preferredTerms.get(i); - if (t.equals(tt.name)) + if (t.equalsIgnoreCase(tt.name)) { return true; } } return res; @@ -124,7 +124,7 @@ void addConcept(ThesaurusConcept c) public boolean equals(Object x) { if (x instanceof ThesaurusTerm) { ThesaurusTerm tt = (ThesaurusTerm) x; - return tt.name.equals(name); + return tt.name.equalsIgnoreCase(name); } return false; } @@ -153,16 +153,20 @@ public static double findSimilarity(String fnme, String fenme, Vector thesaurus) { String nme = fnme.toLowerCase(); String enme = fenme.toLowerCase(); - if (nme.equals(enme)) { return 1.0; } + if (nme.equalsIgnoreCase(enme)) { return 1.0; } if (nme.startsWith(enme)) { return 2.0/3; } if (nme.endsWith(enme)) { return 2.0/3; } if (enme.startsWith(nme)) { return 2.0/3; } if (enme.endsWith(nme)) { return 2.0/3; } String suff = ModelElement.longestCommonSuffix(nme,enme); - if (suff.length() > 0) + if (suff.length() > 1) { return suff.length()/(1.0*Math.max(fnme.length(),fenme.length())); } + String pref = ModelElement.longestCommonPrefix(nme,enme); + if (pref.length() > 1) + { return pref.length()/(1.0*Math.max(fnme.length(),fenme.length())); } + for (int i = 0; i < thesaurus.size(); i++) { ThesaurusConcept tc = (ThesaurusConcept) thesaurus.get(i); if (tc.hasPreferredTerm(nme)) @@ -173,8 +177,8 @@ public static double findSimilarity(String fnme, String fenme, Vector thesaurus) for (int i = 0; i < thesaurus.size(); i++) { ThesaurusConcept tc = (ThesaurusConcept) thesaurus.get(i); - if (tc.hasTerm(nme)) - { if (tc.hasTerm(enme)) + if (tc.hasAnyTerm(nme)) + { if (tc.hasAnyTerm(enme)) { return 2.0/3; } } } diff --git a/TransformationRule.java b/TransformationRule.java index 39c232d2..73e607a9 100644 --- a/TransformationRule.java +++ b/TransformationRule.java @@ -20,10 +20,10 @@ public class TransformationRule boolean isAbstract = false; Attribute source; - Expression guard; + Expression guard = null; Vector targets = new Vector(); // of Attribute Statement body; - TransformationRule superclass; + TransformationRule extending = null; public TransformationRule(String n, boolean l, boolean p) { name = n; @@ -32,12 +32,23 @@ public TransformationRule(String n, boolean l, boolean p) guard = new BasicExpression(true); } + public TransformationRule(EntityMatching em) + { name = em.getName(); + lazy = false; + primary = false; + guard = new BasicExpression(true); + } + + public String getName() { return name; } public boolean isAbstract() { return isAbstract; } + public void setAbstract(boolean b) + { isAbstract = b; } + public void setLazy(boolean b) { lazy = b; } @@ -53,6 +64,23 @@ public void setSource(Attribute s) public void setBody(Statement s) { body = s; } + public void addBody(Statement s) + { Vector newbody = new Vector(); + if (body == null) + { body = s; } + else + { newbody.add(body); + newbody.add(s); + body = new SequenceStatement(newbody); + } + } + + public void setExtends(TransformationRule ext) + { extending = ext; } + + public void setExtends(EntityMatching ext) + { extending = new TransformationRule(ext.getName(),false,false); } + public void addTarget(Attribute trg) { targets.add(trg); } @@ -62,6 +90,52 @@ public void addTargets(Vector trgs) public Attribute getSource() { return source; } + public void addClause(OutPatternElement atlClause) + { // add the variable as a new local variable and the code to the body + Vector stats = new Vector(); + + Attribute var = atlClause.getVariable(); + if (var != null) + { if (targets.size() == 0) + { targets.add(var); } + else + { CreationStatement decvar = new CreationStatement(var.getType() + "", var.getName()); + decvar.setInitialValue("new MM2!" + var.getClassType()); + stats.add(decvar); + } + } + + + Vector binds = atlClause.getBindings(); + for (int i = 0; i < binds.size(); i++) + { Binding bd = (Binding) binds.get(i); + Statement stat = bd.toStatement(); + stats.add(stat); + } // but a conditional case if RHS of the main assignment to var has 0..1 multiplicity + + Statement clausebody = new SequenceStatement(stats); + Expression cond = atlClause.getCondition(); + if (cond == null) + { if (body == null) + { body = clausebody; } + else + { stats.add(0,body); + body = new SequenceStatement(stats); + } + } + else + { clausebody.setBrackets(true); + if (body == null) + { body = new ConditionalStatement(cond,clausebody); } + else + { Vector newstats = new Vector(); + newstats.add(body); + newstats.add(new ConditionalStatement(cond,clausebody)); + body = new SequenceStatement(newstats); + } + } + } + public Expression applicationCondition(Expression selfvar) { Type typ = source.getType(); if (typ != null) @@ -164,24 +238,27 @@ public String toString() if (isAbstract) { res = res + "@abstract\n"; } - res = "rule " + name + "\n" + - " transform " + source.getName() + " : " + source.getType() + "\n" + + res = res + "rule " + name + "\n" + + " transform " + source.getName() + " : MM1!" + source.getType() + "\n" + " to "; for (int i = 0; i < targets.size(); i++) { Attribute trg = (Attribute) targets.get(i); - res = res + trg.getName() + " : " + trg.getType(); + res = res + trg.getName() + " : MM2!" + trg.getType(); if (i < targets.size() - 1) { res = res + ", "; } res = res + "\n "; } - if (guard != null) - { res = res + " { guard: " + guard + "\n " + - body + " }\n"; + if (extending != null) + { res = res + " extends " + extending.getName(); } + + if (guard != null && !("true".equals(guard + ""))) + { res = res + " { guard: (" + guard + ")\n " + + body.toEtl() + " }\n"; } else { res = res + " {\n " + - body + " }\n"; + body.toEtl() + " }\n"; } return res; @@ -473,6 +550,9 @@ public void getCallGraph(Map res) Vector bfcalls = body.allOperationsUsedIn(); for (int j = 0; j < bfcalls.size(); j++) { res.add_pair(name, bfcalls.get(j)); } + + if (extending != null) + { res.add_pair(name, extending.getName()); } } public int analyseEFO(Map m) diff --git a/Type.java b/Type.java index df93fc16..28704e3d 100644 --- a/Type.java +++ b/Type.java @@ -69,6 +69,8 @@ public boolean isSetType() public boolean isSequenceType() { return "Sequence".equals(name); } + public boolean isMapType() + { return "Map".equals(name); } public Object clone() { Type result; @@ -112,6 +114,22 @@ public boolean isSorted() public Entity getEntity() { return entity; } + public Vector metavariables() + { Vector res = new Vector(); + if (name.startsWith("_")) + { res.add(name); } + if ("Sequence".equals(name) && elementType != null) + { return elementType.metavariables(); } + else if ("Set".equals(name) && elementType != null) + { return elementType.metavariables(); } + else if ("Map".equals(name)) + { Vector vars = keyType.metavariables(); + vars.addAll(elementType.metavariables()); + return vars; + } + return res; + } + public int complexity() { if ("Sequence".equals(name) && elementType != null) { return 1 + elementType.complexity(); } @@ -170,6 +188,12 @@ public boolean isNumericType() return false; } + public boolean isStringType() + { if ("String".equals(name)) + { return true; } + return false; + } + public static Type getImageType(Type t, Vector ems) { if (t == null) { return null; } @@ -279,6 +303,12 @@ public static boolean isRecursiveSubtype(Type t1, Type t2) return Type.isRecursiveSubtype(et1,et2); } + if (t1name.equals("Map") && t2name.equals("Map")) + { Type et1 = t1.getElementType(); + Type et2 = t2.getElementType(); + return Type.isRecursiveSubtype(et1,et2); + } + return false; } @@ -481,6 +511,12 @@ public static boolean isSubType(Type t1, Type t2, Map mm, Vector entities) return Type.isSubType(et1,et2,mm,entities); } + if (t1name.equals("Map") && t2name.equals("Map")) + { Type et1 = t1.getElementType(); + Type et2 = t2.getElementType(); + return Type.isSubType(et1,et2,mm,entities); + } + return false; } @@ -512,6 +548,47 @@ public static String booleanEnumConversionFunction(Type e, String srcnme) return ""; } + public static BehaviouralFeature booleanEnumConversionFunctionETL(Type e, String srcnme) + { if (e.isEnumeration()) + { String nme = e.getName(); + double best = 0; + String bestval = (String) e.values.get(0); + double worst = 1; + String worstval = (String) e.values.get(e.values.size() - 1); + + for (int i = 0; i < e.values.size(); i++) + { String val = (String) e.values.get(i); + double sim = ModelElement.similarity(val,srcnme); + if (sim > best) + { best = sim; + bestval = val; + } + if (sim < worst) + { worst = sim; + worstval = val; + } + } + + Type restype = new Type("MM2!" + nme,null); + Type btype = new Type("Boolean",null); + Vector pars = new Vector(); + Attribute p = new Attribute("self",btype); + // pars.add(p); + BehaviouralFeature bf = new BehaviouralFeature("boolean2" + nme + srcnme,pars,true,restype); + bf.setOwner(new Entity("Boolean")); + ReturnStatement assignbest = + new ReturnStatement(new BasicExpression("MM2!" + nme + "#" + bestval)); + ReturnStatement assignworst = + new ReturnStatement(new BasicExpression("MM2!" + nme + "#" + worstval)); + BinaryExpression vtrue = + new BinaryExpression("=",new BasicExpression(p),new BasicExpression(true)); + ConditionalStatement cs = new ConditionalStatement(vtrue,assignbest,assignworst); + bf.setActivity(cs); + return bf; + } + return null; + } + public static String enumBooleanConversionFunction(Type e, String trgnme) { if (e.isEnumeration()) { String nme = e.getName(); @@ -534,6 +611,39 @@ public static String enumBooleanConversionFunction(Type e, String trgnme) return ""; } + public static BehaviouralFeature enumBooleanConversionFunctionETL(Type e, String trgnme) + { if (e.isEnumeration()) + { String nme = e.getName(); + double best = 0; + String bestval = (String) e.values.get(0); + + for (int i = 0; i < e.values.size(); i++) + { String val = (String) e.values.get(i); + double sim = ModelElement.similarity(val,trgnme); + if (sim > best) + { best = sim; + bestval = val; + } + } + + Type restype = new Type("MM2!" + nme,null); + Type btype = new Type("Boolean",null); + Vector pars = new Vector(); + Attribute p = new Attribute("self",restype); + // pars.add(p); + BehaviouralFeature bf = new BehaviouralFeature(nme + "2boolean" + trgnme,pars,true,btype); + bf.setOwner(new Entity("MM2!" + nme)); + ReturnStatement returntrue = new ReturnStatement(new BasicExpression(true)); + ReturnStatement returnfalse = new ReturnStatement(new BasicExpression(false)); + BinaryExpression isbest = + new BinaryExpression("=",new BasicExpression(p),new BasicExpression("#" + bestval)); + ConditionalStatement cs = new ConditionalStatement(isbest,returntrue,returnfalse); + bf.setActivity(cs); + return bf; + } + return null; + } + public static String stringEnumConversionFunction(Type e) { if (e.isEnumeration()) { String nme = e.getName(); @@ -793,6 +903,63 @@ private String enumcases2EnumATL() return res + endres; } + public static BehaviouralFeature enumStringConversionFunctionETL(Type e1) + { String res = " helper def: " + e1.getName() + "2String" + + "(s : MM1!" + e1.getName() + ") : String =\n "; + String restail = ""; + + Vector pars = new Vector(); + Type restype = new Type("String", null); + BehaviouralFeature bf = new BehaviouralFeature("" + e1.getName() + "2String", + pars,true,restype); + bf.setOwner(new Entity("MM1!" + e1.getName())); + + Vector values1 = e1.getValues(); + int s1 = values1.size(); + + String lastval = (String) values1.get(s1 - 1); + BasicExpression lastvale = new BasicExpression("\"" + lastval + "\""); + Statement code = new ReturnStatement(lastvale); + + for (int j = 0; j < s1-1; j++) + { String val = (String) values1.get(j); + BasicExpression vale = new BasicExpression("\"" + val + "\""); + code = new ConditionalStatement(new BasicExpression("self = #" + val), + new ReturnStatement(vale),code); + } + bf.setActivity(code); + return bf; + } + + public static BehaviouralFeature stringEnumConversionFunctionETL(Type e1) + { String res = " helper def: String2" + e1.getName() + + "(s : String) : MM2!" + e1.getName() + " =\n "; + + Vector pars = new Vector(); + Type restype = new Type("MM2!" + e1.getName(), null); + BehaviouralFeature bf = new BehaviouralFeature("String2" + e1.getName(), + pars,true,restype); + bf.setOwner(new Entity("String")); // HACK + + String name1 = e1.getName(); + + Vector values1 = e1.getValues(); + int s1 = values1.size(); + + String lastval = (String) values1.get(s1 - 1); + BasicExpression lastvale = new BasicExpression("MM2!" + name1 + "#" + lastval); + Statement code = new ReturnStatement(lastvale); + + for (int j = 0; j < s1-1; j++) + { String val = (String) values1.get(j); + BasicExpression vale = new BasicExpression("MM2!" + name1 + "#" + val); + code = new ConditionalStatement(new BasicExpression("self = \"" + val + "\""), + new ReturnStatement(vale),code); + } + bf.setActivity(code); + return bf; + } + public String initialValueJava6() // not used? { if (isSequenceType(this)) { return "new ArrayList()"; } @@ -895,6 +1062,12 @@ public boolean hasValue(String st) return values.contains(st); } + public boolean hasValue(Expression st) + { if (values == null) + { return false; } + return values.contains(st + ""); + } + public boolean valueClash(Vector vals) { if (values == null) { return false; } for (int i = 0; i < vals.size(); i++) @@ -1145,6 +1318,74 @@ public static String enum2enumOp(Type e1, Type e2) return res + ";\n\n"; } + public static BehaviouralFeature enumConversionFunctionETL(Type e1, Type e2, Vector thesaurus) + { String res = " helper def: convert" + e1.getName() + "_" + e2.getName() + + "(s : MM1!" + e1.getName() + ") : MM2!" + e2.getName() + " =\n "; + String restail = ""; + + Vector pars = new Vector(); + Type restype = new Type("MM2!" + e2.getName(), null); + BehaviouralFeature bf = new BehaviouralFeature("convert" + e1.getName() + "_" + e2.getName(), + pars,true,restype); + bf.setOwner(new Entity("MM1!" + e1.getName())); + + String name1 = e1.getName().toLowerCase(); + String name2 = e2.getName().toLowerCase(); + + Vector values1 = e1.getValues(); + Vector values2 = e2.getValues(); + int s1 = values1.size(); + int s2 = values2.size(); + + String lastval = (String) values1.get(values1.size() - 1); + double bestscore1 = 0; + String besttarget1 = values2.get(0) + ""; + + for (int j = 0; j < values2.size(); j++) + { String valt = (String) values2.get(j); + double namesim = ModelElement.similarity(lastval,valt); + double namesemsim = Entity.nmsSimilarity(lastval,valt, thesaurus); + double nsim = (namesim + namesemsim - namesim*namesemsim); + if (nsim > bestscore1) + { bestscore1 = nsim; + besttarget1 = valt; + } + } + + Statement code; + if (bestscore1 > 0) + { code = new ReturnStatement(new BasicExpression("#" + besttarget1)); } + else + { code = new SequenceStatement(); } // should not occur + + for (int i = 0; i < values1.size() - 1; i++) + { double bestscore = 0; + String besttarget = values2.get(0) + ""; + + String val = (String) values1.get(i); + + for (int j = 0; j < values2.size(); j++) + { String valt = (String) values2.get(j); + double namesim = ModelElement.similarity(val,valt); + double namesemsim = Entity.nmsSimilarity(val,valt, thesaurus); + double nsim = (namesim + namesemsim - namesim*namesemsim); + if (nsim > bestscore) + { bestscore = nsim; + besttarget = valt; + } + } + + if (bestscore > 0) + { code = new ConditionalStatement(new BasicExpression("self = #" + val), + new ReturnStatement(new BasicExpression("#" + besttarget)), + code); + } + } + + bf.setActivity(code); + return bf; + } + public double enumBooleanSimilarity() { int s1 = values.size(); if (s1 <= 1) @@ -1194,6 +1435,24 @@ public static boolean isBasicType(Type e) return e.isPrimitive(); } + public boolean isValueType() + { if (isBasicType(this)) + { return true; } + + if ("Sequence".equals(name) && elementType != null) + { return elementType.isValueType(); } + else if ("Set".equals(name) && elementType != null) + { return elementType.isValueType(); } + + return false; + } + + public static boolean isValueType(Type t) + { if (t == null) + { return false; } + return t.isValueType(); + } + public int typeMultiplicity() { String nme = getName(); if (nme.equals("int") || nme.equals("double") || nme.equals("boolean") || @@ -1216,7 +1475,7 @@ public boolean isMultiple() if (nme.equals("Map")) { return elementType.isMultiple(); } return false; - } + } // Shouldn't Maps be multiple anyway? public boolean isParsable() { String nme = getName(); @@ -1555,7 +1814,12 @@ else if (nme.startsWith("Set") || nme.startsWith("Sequence") || nme.startsWith(" res.setType(this); res.setElementType(elemt); } - else + else if (isEntity()) + { res = new BasicExpression("null"); + res.setType(this); + res.setElementType(elemt); + } + else // unknown type { res = new BasicExpression(0); } } else @@ -1695,6 +1959,43 @@ public String getCSharp() return "int"; } + public String getSwift(String elemType) + { String nme = getName(); + if (nme.equals("Set")) + { return "Set<" + elemType + ">"; } + if (nme.equals("Sequence")) + { return "[" + elemType + "]"; } + if (nme.equals("Map")) + { return "Dictionary"; } + if (nme.equals("String")) { return "String"; } + if (nme.equals("boolean")) { return "Bool"; } + if (nme.equals("int")) { return "Int"; } + if (nme.equals("long")) { return "Int"; } + if (nme.equals("double")) { return "Double"; } + if (isEntity) { return nme; } + return nme; // enumerations + } + + public String getSwift() + { String nme = getName(); + if (nme.equals("String")) { return "String"; } + if (nme.equals("boolean")) { return "Bool"; } + if (nme.equals("int")) { return "Int"; } + if (nme.equals("long")) { return "Int"; } + if (nme.equals("double")) { return "Double"; } + if (isEntity) { return nme; } + if (isEnumeration()) { return nme; } + + String elemType = elementType.getSwift(); + if (nme.equals("Set")) + { return "Set<" + elemType + ">"; } + if (nme.equals("Sequence")) + { return "[" + elemType + "]"; } + if (nme.equals("Map")) + { return "Dictionary"; } + return nme; + } + public String getCPP(String elemType) { String nme = getName(); if (nme.equals("Set")) @@ -2021,7 +2322,8 @@ public String typeWrapperJava7() // for Java7 if ("boolean".equals(nme)) { return "Boolean"; } if (values != null) { return "Integer"; } return nme; - } + } // For enumerations, would be better to represent as Java enums. + /* public void asTextModel(PrintWriter out) { String nme = getName(); @@ -2236,7 +2538,7 @@ public String toString() } if ("Map".equals(nme)) - { return nme + "(" + keyType + ", " + elementType + ")"; } + { return nme + "(" + keyType + "," + elementType + ")"; } return nme; } @@ -2298,9 +2600,8 @@ else if ("Sequence".equals(nme)) return res; } else - { return t; } - - } + { return t; } + } // Map(String, T) composed with R is Map(String, T composed with R)? public static int composeMultiplicities(Vector atts, String bound) { int res = 1; @@ -2317,17 +2618,72 @@ public static int composeMultiplicities(Vector atts, String bound) public String cg(CGSpec cgs) { String typetext = this + ""; Vector args = new Vector(); - if (isCollectionType()) - { args.add(elementType + ""); } + if (isMapType()) + { args.add(keyType.cg(cgs)); + args.add(elementType.cg(cgs)); + } + else if (isCollectionType()) + { args.add(elementType.cg(cgs)); } else { args.add(typetext); } CGRule r = cgs.matchedTypeUseRule(this,typetext); + System.out.println(">>> Matched rule " + r + " for type " + this + " " + args); + if (r != null) { return r.applyRule(args); } return typetext; } + public String cgEnum(CGSpec cgs) + { String typetext = this + ""; + Vector args = new Vector(); + String arg = ""; + Vector lits = new Vector(); + + for (int i = 0; i < values.size(); i++) + { String v = (String) values.get(i); + EnumLiteral lit = new EnumLiteral(v); + lits.add(lit); + } + String litstring = cgLiteralsList(lits,cgs); + + args.add(getName()); + args.add(litstring); + + CGRule r = cgs.matchedEnumerationRule(this,typetext); + if (r != null) + { return r.applyRule(args); } + return typetext; + } + + public String cgLiteralsList(Vector literals, CGSpec cgs) + { if (literals.size() == 1) + { EnumLiteral lit = (EnumLiteral) literals.get(0); + String text = "literal " + lit; + Vector args = new Vector(); + args.add(lit + ""); + CGRule r = cgs.matchedEnumerationRule(lit,text); + if (r != null) + { return r.applyRule(args); } + return lit + ""; + } + else + { EnumLiteral lit1 = (EnumLiteral) literals.get(0); + Vector taillits = new Vector(); + taillits.addAll(literals); + taillits.remove(0); + String stail = cgLiteralsList(taillits,cgs); + Vector args = new Vector(); + args.add(lit1 + ""); + args.add(stail); + CGRule r = cgs.matchedEnumerationRule(literals,""); + if (r != null) + { return r.applyRule(args); } + return lit1 + ", " + stail; + } + } + public static void main(String[] args) { /* Boolean b = new Boolean(true); @@ -2345,6 +2701,34 @@ public static void main(String[] args) Type t1 = new Type("T1", v1); Type t2 = new Type("T2", v2); - System.out.println(Type.enumSimilarity(t1,t2)); + System.out.println(Type.enumSimilarity(t1,t2)); + + Type tt = new Type("Map",null); + tt.setElementType(t1); + + + System.out.println(tt); + } } + +class EnumLiteral +{ String value = ""; + + EnumLiteral(String v) + { value = v; } + + public String toString() + { return value; } + + public String cg(CGSpec cgs) + { String typetext = this + ""; + Vector args = new Vector(); + args.add(typetext); + + CGRule r = cgs.matchedEnumerationRule(this,typetext); + if (r != null) + { return r.applyRule(args); } + return typetext; + } +} diff --git a/TypeMatching.java b/TypeMatching.java new file mode 100644 index 00000000..230a14ea --- /dev/null +++ b/TypeMatching.java @@ -0,0 +1,61 @@ +import java.util.Vector; +import java.util.Set; +import java.util.HashSet; + + +public class TypeMatching +{ // Created from the enum-enum matchings etc, and + // used to generate data-conversion functions in every MT language + + Type src; + Type trg; + Vector valueMappings = new Vector(); + + public TypeMatching(Type s, Type t) + { src = s; + trg = t; + } + + public void addValueMapping(Expression s, Expression t) + { ValueMatching v = new ValueMatching(s,t); + valueMappings.add(v); + } + + public void addValueMapping(ValueMatching vm) + { + valueMappings.add(vm); + } + + public String toString() + { String res = src + " |--> " + trg + "\n"; + for (int x = 0; x < valueMappings.size(); x++) + { ValueMatching vm = (ValueMatching) valueMappings.get(x); + res = res + " " + vm + "\n"; + } + return res; + } + + public boolean isBijective() + { Set domain = new HashSet(); + Set range = new HashSet(); + for (int x = 0; x < valueMappings.size(); x++) + { ValueMatching vm = (ValueMatching) valueMappings.get(x); + domain.add(vm.src + ""); + range.add(vm.trg + ""); + } + if (domain.size() == range.size() && + domain.size() == valueMappings.size()) + { return true; } + return false; + } + + public TypeMatching invert() + { TypeMatching res = new TypeMatching(trg,src); + for (int x = 0; x < valueMappings.size(); x++) + { ValueMatching vm = (ValueMatching) valueMappings.get(x); + ValueMatching ivm = vm.invert(); + res.addValueMapping(ivm); + } + return res; + } +} diff --git a/UCDArea.java b/UCDArea.java index 0d07fc6a..aeb7cdee 100644 --- a/UCDArea.java +++ b/UCDArea.java @@ -10,9 +10,9 @@ /* * Classname : UCDArea * - * Version information : 1.9 + * Version information : 1.9-2.0 * - * Date : June 2019 + * Date : April 2020 * * Description: This class describes the area that all the painting for * the CD diagram will be performed and deals with painting them @@ -144,6 +144,7 @@ public class UCDArea extends JPanel private Vector imported = new Vector(); // of String private Vector entitymaps = new Vector(); // of EntityMatching + private ModelMatching tlspecification = null; // Parent frame: UmlTool parent; @@ -231,12 +232,14 @@ public Vector getGeneralUseCases() public void addUseCases(Vector ucs) { for (int i = 0; i < ucs.size(); i++) - { UseCase uc = (UseCase) ucs.get(i); - String nme = uc.getName(); - UseCase uc0 = (UseCase) ModelElement.lookupByName(nme,useCases); - if (uc0 != null) - { System.out.println("Existing use case with name: " + nme); - useCases.remove(uc0); + { if (ucs.get(i) instanceof UseCase) + { UseCase uc = (UseCase) ucs.get(i); + String nme = uc.getName(); + UseCase uc0 = (UseCase) ModelElement.lookupByName(nme,useCases); + if (uc0 != null) + { System.out.println("Existing use case with name: " + nme); + useCases.remove(uc0); + } } } for (int i = 0; i < ucs.size(); i++) @@ -418,7 +421,7 @@ else if (editucDialog.isAddAtt()) if (attnme == null) { return; } boolean alreadyDefined = uc.hasAttribute(attnme); if (alreadyDefined) - { System.err.println("Use case already has attribute " + attnme + " not added"); + { System.err.println("!! ERROR: Use case already has attribute " + attnme + " not added"); return; } @@ -433,7 +436,7 @@ else if (editucDialog.isAddAtt()) tt = new Type(typ,null); } else - { System.out.println("Invalid type name: " + typ); + { System.out.println("!!! Invalid type name: " + typ); JOptionPane.showMessageDialog(null, "Error: invalid type " + typ, "", JOptionPane.ERROR_MESSAGE); @@ -647,9 +650,9 @@ public void addUseCasePostcondition(UseCase uc, Invariant inv) boolean tc = inv.typeCheck(types,entities,contexts,newparams); if (tc) - { System.out.println("Postcondition type-checked correctly"); } + { System.out.println(">> Postcondition type-checked correctly"); } else - { System.out.println("Postcondition not correctly typed!"); } + { System.out.println("!! Postcondition not correctly typed!"); } Constraint cons = new Constraint((SafetyInvariant) inv,new Vector()); cons.setOwner(owner); @@ -665,7 +668,7 @@ public void addUseCasePostcondition(UseCase uc, Invariant inv) { uc.addPostcondition(cons); cons.setUseCase(uc); uc.resetDesign(); - System.out.println("The use case design has been reset"); + System.out.println(">> The use case design has been reset"); } } @@ -739,7 +742,7 @@ public void editUseCaseConstraints(UseCase uc, Vector cons) { System.err.println(messages); } Expression eAssump = comp.parse(); if (eAssump == null) - { eAssump = new BasicExpression("true"); } + { eAssump = new BasicExpression(true); } comp = new Compiler2(); comp.nospacelexicalanalysis(sConc); Vector succsymbs = new Vector(); @@ -749,7 +752,7 @@ public void editUseCaseConstraints(UseCase uc, Vector cons) { System.err.println(messages); } Expression eConc = comp.parse(); if (eConc == null) - { eConc = new BasicExpression("true"); } + { eConc = new BasicExpression(true); } // boolean isSys = sinvDialog.isSystem(); // boolean isCrit = sinvDialog.isCritical(); @@ -874,23 +877,28 @@ private void addUseCaseExtends(UseCase uc) // check that ucinc is not already an extension of an extends, or inclusion of // an includes: for (int i = 0; i < useCases.size(); i++) - { UseCase uc1 = (UseCase) useCases.get(i); - if (uc1.hasExtension(ucext)) - { System.err.println("Cannot have " + nme + " as extension of two usecases!"); - return; - } + { if (useCases.get(i) instanceof UseCase) + { UseCase uc1 = (UseCase) useCases.get(i); + if (uc1.hasExtension(ucext)) + { System.err.println("Cannot have " + nme + " as extension of two usecases!"); + return; + } + } } for (int i = 0; i < useCases.size(); i++) - { UseCase uc1 = (UseCase) useCases.get(i); - if (uc1.hasInclusion(ucext)) - { System.err.println("Cannot have " + nme + " as extension and inclusion!"); - return; + { if (useCases.get(i) instanceof UseCase) + { UseCase uc1 = (UseCase) useCases.get(i); + if (uc1.hasInclusion(ucext)) + { System.err.println("Cannot have " + nme + " as extension and inclusion!"); + return; + } } } Extend ee = new Extend(uc,ucext); uc.addExtension(ee); + ucext.addExtensionOf(uc); // Draw dashed line from ucext to uc drawDependency(ucext, uc, "<>"); } @@ -922,17 +930,20 @@ private void addUseCaseIncludes(UseCase uc) // check that ucinc is not already an extension of an extends: for (int i = 0; i < useCases.size(); i++) - { UseCase uc1 = (UseCase) useCases.get(i); - if (uc1.hasExtension(ucinc)) - { System.err.println("Cannot have " + nme + " as extension and inclusion!"); - JOptionPane.showMessageDialog(null, "Error: " + nme + " is extension & inclusion!", + { if (useCases.get(i) instanceof UseCase) + { UseCase uc1 = (UseCase) useCases.get(i); + if (uc1.hasExtension(ucinc)) + { System.err.println("Cannot have " + nme + " as extension and inclusion!"); + JOptionPane.showMessageDialog(null, "Error: " + nme + " is extension & inclusion!", "",JOptionPane.ERROR_MESSAGE); - return; + return; + } } } Include ee = new Include(uc,ucinc); uc.addInclude(ee); + ucinc.addIncludedIn(uc); drawDependency(uc, ucinc, "<>"); } @@ -1018,7 +1029,7 @@ private void addUseCaseOperation(UseCase uc) typ.equals("double") || typ.equals("boolean")) { tt = new Type(typ,null); } else - { System.err.println("Invalid type name: " + typ); + { System.err.println("!! ERROR: Invalid type name: " + typ); tt = null; } } @@ -1064,7 +1075,7 @@ private void addUseCaseOperation(UseCase uc) { System.err.println("Failed to type-check precondition"); } if (post == null) - { System.err.println("Invalid postcondition"); + { System.err.println(">>> Invalid postcondition"); post = "true"; } @@ -1219,7 +1230,7 @@ private void editUseCaseOperation(UseCase uc) boolean tc = spre.typeCheck(types,entities,contexts,vars); if (!tc) - { System.err.println("Warning: Unable to type-check precondition " + cond); } + { System.err.println("!! Warning: Unable to type-check precondition " + cond); } if (post == null) { System.err.println("ERROR: Invalid postcondition"); @@ -1391,8 +1402,8 @@ public UseCase expandUseCase(UseCase uc) } public void addInvariant(Invariant inv) - { System.out.println("Select associations or entity that invariant is attached to"); - System.out.println("And/or the use case to which it belongs as a postcondition"); + { System.out.println(">>> Select associations or entity that invariant is attached to"); + System.out.println(">>> And/or the use case to which it belongs as a postcondition"); String anames = JOptionPane.showInputDialog("Enter association names, or entity, or entity + use case:"); if (anames == null) @@ -1406,6 +1417,8 @@ public void addInvariant(Invariant inv) String preEntity = ""; int atindex = -1; + Vector env = new Vector(); + while (st.hasMoreTokens()) { String se = st.nextToken().trim(); atindex = se.indexOf('@'); @@ -1429,6 +1442,7 @@ public void addInvariant(Invariant inv) { UseCase uc = (UseCase) ModelElement.lookupByName(se,useCases); if (uc != null) { // System.out.println("Found use case"); + env.addAll(uc.getParameters()); usecase = uc; } } @@ -1439,39 +1453,40 @@ public void addInvariant(Invariant inv) if (owner != null) { contexts.add(owner); } - boolean tc = inv.typeCheck(types,entities,contexts,new Vector()); - if (tc) - { // System.out.println("Invariant type-checked correctly"); - Constraint cons = new Constraint((SafetyInvariant) inv,astv); - for (int i = 0; i < astv.size(); i++) - { Association ast = (Association) astv.get(i); - ast.addConstraint(cons); - } - cons.setOwner(owner); - if (preEntity.length() > 0) - { cons.setisPre(true); } - cons.typeCheck(types,entities,contexts); // to identify variables + boolean tc = inv.typeCheck(types,entities,contexts,env); + if (!tc) + { System.err.println("!! Type error in constraint: " + inv); } + + Constraint cons = new Constraint((SafetyInvariant) inv,astv); + for (int i = 0; i < astv.size(); i++) + { Association ast = (Association) astv.get(i); + ast.addConstraint(cons); + } + cons.setOwner(owner); + if (preEntity.length() > 0) + { cons.setisPre(true); } + + cons.typeCheck(types,entities,contexts); // to identify variables // invariants.add(inv); - System.out.println("read frame of " + cons + " is " + cons.readFrame()); + System.out.println(">> read frame of " + cons + " is " + cons.readFrame()); - if (usecase != null) - { usecase.addPostcondition(cons); - cons.setUseCase(usecase); - if (preEntity.length() > 0) - { cons.setisPre(true); } - - } + if (usecase != null) + { usecase.addPostcondition(cons); + cons.setUseCase(usecase); + if (preEntity.length() > 0) + { cons.setisPre(true); } + } // constraints.add(cons); - boolean local = cons.checkIfLocal(); - if (usecase != null) { } - else if (local) - { owner.addInvariant(cons); } - else - { constraints.add(cons); // global constraint not in a use case + boolean local = cons.checkIfLocal(); + if (usecase != null) { } + else if (local) + { owner.addInvariant(cons); } + else + { constraints.add(cons); // global constraint not in a use case // Vector ents = cons.innermostEntities(); // System.out.println("Needed entities are: " + ents); @@ -1528,9 +1543,7 @@ else if (local) } } */ } - } - else - { System.out.println("ERROR: Invariant not correctly typed, not added: " + inv); } + } public void addInvariant(Invariant inv, Entity owner) @@ -1539,9 +1552,10 @@ public void addInvariant(Invariant inv, Entity owner) { contexts.add(owner); } boolean tc = inv.typeCheck(types,entities,contexts,new Vector()); - if (tc) - { // System.out.println("Invariant type-checked correctly"); - Constraint cons = new Constraint((SafetyInvariant) inv, + if (!tc) + { System.err.println("!! ERROR in type-checking: " + inv); } + + Constraint cons = new Constraint((SafetyInvariant) inv, new Vector()); cons.setOwner(owner); // invariants.add(inv); @@ -1564,12 +1578,7 @@ public void addInvariant(Invariant inv, Entity owner) " not subset of association ends: " + endPoints); } } - } - else - { System.out.println("Invariant not correctly typed, not added: " + inv); - JOptionPane.showMessageDialog(null, "Invariant not correctly typed: " + inv, - "", JOptionPane.WARNING_MESSAGE); - } + } public void removeInvariant(Constraint con) @@ -2329,6 +2338,7 @@ public void addUseCase() { System.err.println("Invalid entity name: " + ent); return; } + if (nme.equals("add") || nme.equals("remove") || nme.equals("create") || nme.equals("delete") || nme.equals("edit") || nme.equals("get") || nme.equals("list") || nme.equals("searchBy") || nme.equals("set")) @@ -2365,16 +2375,13 @@ public void addGeneralUseCase() String nme = ucDialog.getName(); if (nme == null || "".equals(nme)) { return; } - // String ent = ucDialog.getEntity(); + String ent = ucDialog.getEntity(); String desc = ucDialog.getDescription(); String typ = ucDialog.getUseCaseType(); if ("none".equals(typ)) { typ = null; } - // Entity e = (Entity) ModelElement.lookupByName(ent,entities); - // if (e == null) - // { System.err.println("No entity specified"); } UseCase uc = (UseCase) ModelElement.lookupByName(nme,useCases); if (uc != null) @@ -2409,6 +2416,14 @@ public void addGeneralUseCase() useCases.add(ucext); } */ + if (ent != null && ent.length() > 0) + { Entity e = (Entity) ModelElement.lookupByName(ent,entities); + if (e == null) + { System.err.println("!! Invalid associated entity"); } + else + { uc.setEntity(e); } + } + String pars = ucDialog.getParameters(); if (pars == null || pars.trim().length() == 0) { } else @@ -2422,7 +2437,7 @@ public void addGeneralUseCase() Type elemType = null; Type ptt = Type.getTypeFor(ptype, types, entities); if (ptt == null) - { System.err.println("ERROR: Invalid type for parameter: " + pp); } + { System.err.println("!!! ERROR: Invalid type " + ptype + " for parameter: " + pp); } else { Attribute pattr = new Attribute(pp, ptt, ModelElement.INTERNAL); pattr.setElementType(ptt.getElementType()); @@ -2515,7 +2530,7 @@ public void createBacktrackingSpecification(UseCase usec) public void reconstructUseCase(String nme, String ent, String role) { Entity e = (Entity) ModelElement.lookupByName(ent,entities); if (e == null) - { System.err.println("Invalid entity name: " + ent); + { System.err.println("ERROR: Invalid entity name: " + ent); return; } if (nme.equals("add") || nme.equals("remove") || nme.equals("create") || @@ -2896,32 +2911,138 @@ public void saveCSV() } + public void generateIOSApp() + { IOSAppGenerator gen = new IOSAppGenerator(); + CGSpec cgs = loadCSTL(); + // System.out.println(cgs); + + for (int j = 0; j < entities.size(); j++) + { Entity ent = (Entity) entities.get(j); + if (ent.isDerived()) { } + else + { String entvo = ent.getName() + "VO.swift"; + File entvof = new File("output/" + entvo); + try + { PrintWriter voout = new PrintWriter( + new BufferedWriter( + new FileWriter(entvof))); + voout.println(ent.getIOSValueObject("app")); + voout.close(); + } catch (Exception e) { } + } + } + + Vector entusecases = new Vector(); + for (int i = 0; i < useCases.size(); i++) + { if (useCases.get(i) instanceof UseCase) + { UseCase uc = (UseCase) useCases.get(i); + // Vector wrf = uc.wr(associations); + // Vector cwrf = uc.readFrame(); + // System.out.println(">>> " + uc.getName() + " has outputs " + wrf + " and inputs " + cwrf); + // uc.identifyInputsOutputs(associations); + // Entity ucentity = uc.findEntity(entities,associations); + // if (ent == ucentity) + { entusecases.add(uc); } + } + else if (useCases.get(i) instanceof OperationDescription) + { OperationDescription od = (OperationDescription) useCases.get(i); + + String nme = od.getName(); + File odswift = new File("output/" + nme + "ViewController.swift"); + try + { PrintWriter swiftout = new PrintWriter( + new BufferedWriter( + new FileWriter(odswift))); + od.iOSViewController(swiftout); + swiftout.close(); + } catch (Exception e) { } + } + } + String entbean = "ModelFacade.swift"; + File entbeanf = new File("output/" + entbean); + try + { PrintWriter beanout = new PrintWriter( + new BufferedWriter( + new FileWriter(entbeanf))); + System.out.println(">>> Writing " + entbeanf + " for " + entusecases); + + gen.modelFacade(entusecases,cgs,entities, + types,beanout); + beanout.flush(); + beanout.close(); + } catch (Exception e) { } + + for (int z = 0; z < entusecases.size(); z++) + { UseCase uc = (UseCase) entusecases.get(z); + String ucvc = uc.getName() + "ViewController.swift"; + File ucvcf = new File("output/" + ucvc); + try + { PrintWriter vcout = new PrintWriter( + new BufferedWriter( + new FileWriter(ucvcf))); + System.out.println(">>> Writing " + ucvcf + " for " + uc.getName()); + + gen.singlePageApp(uc,cgs,vcout); + vcout.flush(); + vcout.close(); + } catch (Exception e) { } + } + } + public void generateAndroidLayouts(PrintWriter out) - { /* File chtml = new File("output/commands.html"); + { AndroidAppGenerator agen = new AndroidAppGenerator(); + + if (systemName == null || "".equals(systemName)) + { systemName = "myApp"; } + agen.generateManifest(systemName,out); + + File chtml = new File("output/app/src/main/res/layout/activity_main.xml"); try { PrintWriter chout = new PrintWriter( new BufferedWriter( new FileWriter(chtml))); - chout.println(generateCommandHtml(useCases)); - // out.println(); + OperationDescription.androidCreateMenu(useCases,chout); chout.close(); - } catch (Exception e) { } */ + } catch (Exception e) { } + + File codefile = new File("output/app/src/main/java/MainActivity.java"); + try + { PrintWriter codeout = new PrintWriter( + new BufferedWriter( + new FileWriter(codefile))); + OperationDescription.androidCreateMainActivity(useCases,codeout); + codeout.close(); + } catch (Exception e) { } + Vector referencedEntities = new Vector(); for (int i = 0; i < useCases.size(); i++) { Object obj = useCases.get(i); if (obj instanceof OperationDescription) { OperationDescription od = (OperationDescription) obj; - od.androidScreen(out); + File odlayout = new File("output/app/src/main/res/layout/" + od.getName() + "_layout.xml"); + try + { PrintWriter odlayoutfile = new PrintWriter( + new BufferedWriter( + new FileWriter(odlayout))); + od.androidScreen(odlayoutfile); + odlayoutfile.close(); + } catch (Exception e) { } + + if (od.entity != null) + { if (referencedEntities.contains(od.entity)) { } + else + { referencedEntities.add(od.entity); } + } String nme = od.getName(); - File odjsp = new File("output/View" + nme + ".java"); + File odjsp = new File("output/app/src/main/java/View" + nme + ".java"); try { PrintWriter jspout = new PrintWriter( - new BufferedWriter( - new FileWriter(odjsp))); - od.androidViewActivity(jspout); + new BufferedWriter( + new FileWriter(odjsp))); + od.androidViewActivity(systemName,jspout); jspout.close(); } catch (Exception e) { } @@ -2936,22 +3057,54 @@ public void generateAndroidLayouts(PrintWriter out) odhout.close(); } catch (Exception e) { } */ } + else if (obj instanceof UseCase) + { UseCase uc = (UseCase) obj; + if (uc.includedIn.size() == 0 && uc.extensionOf.size() == 0) + { Vector extensions = uc.extensionUseCases(); + String nme = uc.getName(); + Vector atts = uc.getParameters(); + Attribute res = uc.getResultParameter(); + + File opfile = new File("output/app/src/main/res/layout/" + nme + "_layout.xml"); + try + { PrintWriter opout = new PrintWriter( + new BufferedWriter( + new FileWriter(opfile))); + if (extensions.size() > 0) + { OperationDescription.androidTableLayoutForOps(nme,atts,res,extensions,opout); } + else + { OperationDescription.androidTableLayoutForOp(nme,atts,res,opout); } + opout.close(); + } catch (Exception e) { } + + File odact = new File("output/app/src/main/java/" + nme + "Activity.java"); + try + { PrintWriter actout = new PrintWriter( + new BufferedWriter( + new FileWriter(odact))); + OperationDescription.androidOpViewActivity(nme,atts,res,extensions,actout); + actout.close(); + } catch (Exception e) { } + } + } } for (int j = 0; j < entities.size(); j++) - { Entity ent = (Entity) entities.get(j); + { Entity ent = (Entity) entities.get(j); + if (ent.isDerived()) { continue; } + String entvo = ent.getName() + "VO.java"; - File entvof = new File("output/" + entvo); + File entvof = new File("output/app/src/main/java/" + entvo); try { PrintWriter voout = new PrintWriter( new BufferedWriter( new FileWriter(entvof))); - voout.println(ent.getAndroidValueObject()); + voout.println(ent.getAndroidValueObject(systemName)); voout.close(); } catch (Exception e) { } String entbean = ent.getName() + "Bean.java"; - File entbeanf = new File("output/" + entbean); + File entbeanf = new File("output/app/src/main/java/" + entbean); try { PrintWriter beanout = new PrintWriter( new BufferedWriter( @@ -2961,14 +3114,52 @@ public void generateAndroidLayouts(PrintWriter out) } catch (Exception e) { } } - File dbif = new File("output/Dbi.java"); + for (int j = 0; j < useCases.size(); j++) + { if (useCases.get(j) instanceof UseCase) + { UseCase uc = (UseCase) useCases.get(j); + String ucvo = uc.getName() + "VO.java"; + File ucvof = new File("output/app/src/main/java/" + ucvo); + try + { PrintWriter voout = new PrintWriter( + new BufferedWriter( + new FileWriter(ucvof))); + voout.println(uc.getAndroidValueObject()); + voout.close(); + } catch (Exception e) { } + + String ucbean = uc.getName() + "Bean.java"; + File ucbeanf = new File("output/app/src/main/java/" + ucbean); + try + { PrintWriter beanout = new PrintWriter( + new BufferedWriter( + new FileWriter(ucbeanf))); + beanout.println(uc.generateAndroidBean(entities,types)); + beanout.close(); + } catch (Exception e) { } + } + } + + File dbif = new File("output/app/src/main/java/Dbi.java"); try { PrintWriter dbiout = new PrintWriter( new BufferedWriter( new FileWriter(dbif))); - generateAndroidDbi(useCases,dbiout); + generateAndroidDbi(referencedEntities,useCases,dbiout); dbiout.close(); } catch (Exception e) { } + + File mff = new File("output/app/src/main/java/ModelFacade.java"); + try + { CGSpec cgs = loadCSTL(); + PrintWriter mfout = new PrintWriter( + new BufferedWriter( + new FileWriter(mff))); + agen.modelFacade(useCases,cgs,entities,types,mfout); + mfout.close(); + } catch (Exception e) + { e.printStackTrace(); } + + // generateIOSApp(out); /* out.println(generateDbiPool()); */ } @@ -3125,12 +3316,12 @@ private void addOperationToEntity(Entity ent) boolean query = opDialog.getQuery(); if (nme == null) // cancelled - { System.err.println("Operation definition cancelled. No name specified"); + { System.err.println(">>> Operation definition cancelled. No name specified"); return; } if (typ == null && query) - { System.err.println("Error: query operation without type"); + { System.err.println("!! Error: query operation without type"); JOptionPane.showMessageDialog(null, "ERROR: query operation must have a return type!", "", JOptionPane.ERROR_MESSAGE); return; } @@ -3155,13 +3346,13 @@ private void addOperationToEntity(Entity ent) Expression cond; Compiler2 comp = new Compiler2(); if (pre == null || pre.equals("")) - { cond = new BasicExpression("true"); } + { cond = new BasicExpression(true); } else { comp.nospacelexicalanalysis(pre); cond = comp.parse(); if (cond == null) { System.err.println("Warning, precondition has wrong syntax: " + pre); - cond = new BasicExpression("true"); + cond = new BasicExpression(true); } } Expression spre = cond.simplify(); @@ -3178,8 +3369,8 @@ private void addOperationToEntity(Entity ent) } - if (post == null) - { System.out.println("Invalid postcondition"); + if (post == null || post.equals("")) + { System.out.println("!! Invalid postcondition"); post = "true"; } Compiler2 comp1 = new Compiler2(); @@ -3188,7 +3379,8 @@ private void addOperationToEntity(Entity ent) while (effect == null) { System.out.println("Invalid postcondition: " + post); - JOptionPane.showMessageDialog(null, "ERROR: invalid expression: " + post, "", JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(null, + "ERROR: invalid expression: " + post, "", JOptionPane.ERROR_MESSAGE); opDialog.setOldFields(nme,typ,params,pre,post,query); // opDialog.setStereotypes(null); opDialog.setVisible(true); @@ -3203,7 +3395,9 @@ private void addOperationToEntity(Entity ent) if (query) { if (tt == null) - { System.err.println("Error: query operation must have a return type!"); JOptionPane.showMessageDialog(null, "ERROR: query operation must have a return type!", "", JOptionPane.ERROR_MESSAGE); + { System.err.println("Error: query operation must have a return type!"); + JOptionPane.showMessageDialog(null, + "ERROR: query operation must have a return type!", "", JOptionPane.ERROR_MESSAGE); return; } } @@ -3215,12 +3409,12 @@ private void addOperationToEntity(Entity ent) params = opDialog.getParams(); // pairs var type Vector oppars = - BehaviouralFeature.reconstructParameters(params,types,entities); + BehaviouralFeature.reconstructParameters(params," ",types,entities); vars.addAll(oppars); boolean tc = spre.typeCheck(types,entities,contexts,vars); if (!tc) - { System.out.println("Warning: cannot type precondition: " + spre); + { System.out.println("!! Warning: cannot type precondition: " + spre); // spre = new BasicExpression("true"); // return; } @@ -3406,7 +3600,7 @@ private void editOperationFromEntity(Entity ent) Expression effect = comp1.parse(); while (effect == null) - { System.out.println("Invalid postcondition: " + post); + { System.out.println("!! Invalid postcondition: " + post); JOptionPane.showMessageDialog(null, "ERROR: invalid expression!: " + post, "", JOptionPane.ERROR_MESSAGE); opDialog.setOldFields(nme, typ, params, pre, @@ -4488,7 +4682,7 @@ public void removeAssociationClass(Association ast) // same as addInvariant: public Constraint addInvariant(PreConstraint pc) { if (pc.succ == null) - { System.err.println("Constraint not parsed correctly"); + { System.err.println("!! Constraint not parsed correctly"); return null; } @@ -4522,7 +4716,7 @@ public Constraint addInvariant(PreConstraint pc) else { UseCase uc = (UseCase) ModelElement.lookupByName(se,useCases); if (uc != null) - { // System.out.println("Found use case"); + { System.out.println(">> Found use case " + uc.getName()); usecase = uc; } } @@ -4559,11 +4753,13 @@ public Constraint addInvariant(PreConstraint pc) // System.out.println("Prestate owner"); } - if (con.typeCheck(types,entities,contexts,env)) { } - else - { System.err.println("ERROR: Constraint not correctly " + + boolean tc = con.typeCheck(types,entities,contexts,env); + + if (!tc) + { System.err.println("!! ERROR: Constraint not correctly " + "typed: " + con); } + // System.out.println("Invariant type-checked correctly"); con.setBehavioural(pc.succ.isUpdateable()); @@ -4632,7 +4828,7 @@ else if (local) public Constraint addAssertion(PreConstraint pc) { if (pc.succ == null) - { System.err.println("Constraint not parsed correctly"); + { System.err.println("!! Constraint not parsed correctly"); return null; } @@ -4873,7 +5069,7 @@ public Constraint addGenericAssertion(PreConstraint pc, Vector ucs) public Constraint addGenericInvariant(PreConstraint pc, Vector ucs) { if (pc.succ == null) - { System.err.println("Constraint not parsed correctly"); + { System.err.println("ERROR: Constraint not parsed correctly"); return null; } @@ -4898,7 +5094,7 @@ public Constraint addGenericInvariant(PreConstraint pc, Vector ucs) usecase = uc; } else - { System.out.println("Enter instantiation of entity: " + se); + { System.out.println(">> Enter instantiation of entity: " + se); String epar = JOptionPane.showInputDialog("Actual entity of: " + se); Entity e = (Entity) ModelElement.lookupByName(epar,entities); @@ -5034,7 +5230,7 @@ private BehaviouralFeature reconstructOperation(PreOp p) String params = p.params; // pairs var type Vector oppars = - BehaviouralFeature.reconstructParameters(params,types,entities); + BehaviouralFeature.reconstructParameters(params," ",types,entities); String pre = p.pre; String post = p.post; @@ -5061,7 +5257,7 @@ private BehaviouralFeature reconstructOperation(PreOp p) boolean tc = cond.typeCheck(types,entities,contexts,vars); if (!tc) - { System.err.println("Invalid precondition: " + cond); + { System.err.println("!! ERROR: Invalid precondition: " + cond); // return null; JOptionPane.showMessageDialog(null, "ERROR: Invalid precondition " + cond + " for: " + p.name, "Expression error", JOptionPane.ERROR_MESSAGE); @@ -6859,6 +7055,9 @@ private void generateSystemTypes(PrintWriter out) String collops = BSystemTypes.getCollectOps(); out.println(collops); + String aops = BSystemTypes.getAnyOps(); + out.println(aops); + out.println(BSystemTypes.generateSetEqualsOp()); out.println(" public Set add(Object x)"); out.println(" { if (x != null) { elements.add(x); }"); @@ -7023,6 +7222,9 @@ private void generateSystemTypesJava6(PrintWriter out) String collops = BSystemTypes.getCollectOps(); out.println(collops); + String aops = BSystemTypes.getAnyOps(); + out.println(aops); + // out.println(BSystemTypes.generateSetEqualsOp()); out.println(" public static HashSet addSet(HashSet s, Object x)"); out.println(" { if (x != null) { s.add(x); }"); @@ -7207,6 +7409,9 @@ private void generateSystemTypesJava7(PrintWriter out) String collops = BSystemTypes.getCollectOps(); out.println(collops); + String aops = BSystemTypes.getAnyOps(); + out.println(aops); + // out.println(BSystemTypes.generateSetEqualsOp()); out.println(" public static HashSet addSet(HashSet s, T x)"); out.println(" { if (x != null) { s.add(x); }"); @@ -7326,10 +7531,10 @@ private void generateSystemTypesJava7(PrintWriter out) /* Map operations - optional */ - // mop = BSystemTypes.generateIncludesAllMapOpJava7(); - // out.println("\n" + mop); - // mop = BSystemTypes.generateExcludesAllMapOpJava7(); - // out.println("\n" + mop); + mop = BSystemTypes.generateIncludesAllMapOpJava7(); + out.println("\n" + mop); + mop = BSystemTypes.generateExcludesAllMapOpJava7(); + out.println("\n" + mop); mop = BSystemTypes.generateIncludingMapOpJava7(); out.println("\n" + mop); mop = BSystemTypes.generateExcludeAllMapOpJava7(); @@ -7385,6 +7590,9 @@ private void generateSystemTypesCSharp(PrintWriter out) String collops = BSystemTypes.getCollectOps(); out.println(collops); + String aops = BSystemTypes.getAnyOps(); + out.println(aops); + out.println(BSystemTypes.generateSetEqualsOpCSharp()); out.println(" public static ArrayList addSet(ArrayList a, object x)"); out.println(" { ArrayList res = new ArrayList();"); @@ -7535,6 +7743,9 @@ private void generateSystemTypesCPP(PrintWriter out) String collops = BSystemTypes.getCollectOps(); out.println(collops); + String aops = BSystemTypes.getAnyOps(); + out.println(aops); + out.println(" static bool isIn(_T x, set<_T>* st)"); out.println(" { return (st->find(x) != st->end()); }\n"); out.println(" static bool isIn(_T x, vector<_T>* sq)"); @@ -7679,6 +7890,12 @@ private void generateSystemTypesCPP(PrintWriter out) out.println("\n" + mop); mop = BSystemTypes.generateIntersectionMapOpCPP(); out.println("\n" + mop); + mop = BSystemTypes.generateKeysMapOpCPP(); + out.println("\n" + mop); + mop = BSystemTypes.generateValuesMapOpCPP(); + out.println("\n" + mop); + mop = BSystemTypes.generateRestrictOpCPP(); + out.println("\n" + mop); out.println("};"); } @@ -8388,6 +8605,7 @@ private void generateControllerCPP(String mop, PrintWriter out, PrintWriter out2 out.println(BSystemTypes.getExistsOps()); out.println(BSystemTypes.getExists1Ops()); out.println(BSystemTypes.getCollectOps()); + out.println(BSystemTypes.getAnyOps()); // controllerInterface = controllerInterface + "}\n"; // out3.println(controllerInterface); @@ -9149,6 +9367,185 @@ private void saveEcore(PrintWriter out) out.println(""); } + public void loadTL() + { ModelMatching res = new ModelMatching(); + Map mm = new Map(); + + BufferedReader br = null; + String s; + boolean eof = false; + File file = new File("output/forward.tl"); /* default */ + + try + { br = new BufferedReader(new FileReader(file)); } + catch (FileNotFoundException _e) + { System.out.println("File not found: " + file); + return; + } + + int noflines = 0; + + while (!eof) + { try { s = br.readLine(); } + catch (IOException _ex) + { System.out.println("!! Reading TL file failed."); + return; + } + if (s == null) + { eof = true; + break; + } + else if (s.startsWith("--")) { } + else if (s.indexOf("|-->") > 0) + { String trimemap = s.trim(); + int mapsymb = trimemap.indexOf("|"); + if (mapsymb > 0) + { String sents = trimemap.substring(0,mapsymb); + String tents = trimemap.substring(mapsymb + 4, trimemap.length()); + + System.out.println(">> Using match: " + sents + " to " + tents); + + Entity esrc = (Entity) ModelElement.lookupByName(sents.trim(),entities); + Entity etrg = (Entity) ModelElement.lookupByName(tents.trim(),entities); + + Expression precond = null; + if (esrc == null) + { int endprecond = sents.indexOf("}"); + int startprecond = sents.indexOf("{"); + if (endprecond > 0 && startprecond >= 0) + { Compiler2 c2 = new Compiler2(); + String precondstring = sents.substring(startprecond+1,endprecond); + c2.nospacelexicalanalysis(precondstring); + precond = c2.parseExpression(); + String sents1 = sents.substring(endprecond+1,mapsymb).trim(); + esrc = (Entity) ModelElement.lookupByName(sents1,entities); + } + } + + Expression postcond = null; + if (etrg == null) + { int endpostcond = tents.indexOf("}"); + int startpostcond = tents.indexOf("{"); + if (endpostcond > 0 && startpostcond >= 0) + { Compiler2 c3 = new Compiler2(); + String postcondstring = tents.substring(startpostcond+1,endpostcond); + c3.nospacelexicalanalysis(postcondstring); + postcond = c3.parseExpression(); + String tents1 = tents.substring(0,startpostcond).trim(); + etrg = (Entity) ModelElement.lookupByName(tents1,entities); + } + } + + if (esrc != null && etrg != null) + { EntityMatching em = new EntityMatching(esrc,etrg); + System.out.println(">> Using match: " + sents + " to " + tents); + if (precond != null) + { Vector contexts1 = new Vector(); + + contexts1.add(esrc); + precond.typeCheck(types,entities,contexts1,new Vector()); + em.setCondition(precond); + } + if (postcond != null) + { Vector contexts2 = new Vector(); + + contexts2.add(etrg); + postcond.typeCheck(types,entities,contexts2,new Vector()); + em.setPostcondition(postcond); + } + entitymaps.add(em); + Maplet s2t = new Maplet(esrc,etrg); + mm.add(s2t); + AttributeMatching amx = readEntityMapping(br,em); + while (amx != null) + { amx = readEntityMapping(br,em); } + } + } + } + // System.out.println(s); + } + res.addEntityMatchings(entitymaps); + res.mymap = mm; + System.out.println(">>> Parsed TL specification: " + res); + tlspecification = res; + } + + public void applyCSTLSpecification() + { CGSpec spec = loadCSTL(); + + if (spec == null) { return; } + + + String newtypes = ""; + String newclasses = ""; + String newusecases = ""; + + /* Argument _2 of the package rule */ + + for (int i = 0; i < types.size(); i++) + { Type t = (Type) types.get(i); + String newt = t.cgEnum(spec); + newtypes = newtypes + newt + '\n'; + // System.out.println("Transformed type usage " + t + " is " + newt); + } + + /* Argument _3 of the package rule */ + + for (int i = 0; i < entities.size(); i++) + { Entity t = (Entity) entities.get(i); + t.generateOperationDesigns(types,entities); + String newt = t.cg(spec); + newclasses = newclasses + newt + '\n'; + // System.out.println("Transformed entity " + t + " is " + newt); + } + + /* Argument _4 of the package rule */ + + Vector ucs = new Vector(); + + for (int i = 0; i < useCases.size(); i++) + { Object uc = useCases.get(i); + if (uc instanceof UseCase) + { UseCase xx = (UseCase) uc; + ucs.add(xx); + // xx.implementBehaviour(types,entities); + String newt = xx.cg(spec,types,entities); + String arg1 = CGRule.correctNewlines(newt); + newusecases = newusecases + arg1 + '\n'; + } + } + + + File chtml = new File("output/cgout.txt"); + try + { PrintWriter chout = new PrintWriter( + new BufferedWriter( + new FileWriter(chtml))); + + spec.transformPackage(newtypes,newclasses,newusecases, + types,entities,ucs, chout); + + + chout.println(); + + chout.close(); + } catch (Exception e) { } + + } + + public CGSpec loadCSTL() + { CGSpec res = new CGSpec(); + + File f = new File("./cg/cg.cstl"); /* default */ + if (f != null) + { res = CSTL.loadCSTL(f,types,entities); } + + System.out.println(">>> Parsed: " + res); + + CSTL.loadTemplates(types,entities); + return res; + } + public void loadATL() { for (int i = 0; i < entities.size(); i++) @@ -9519,6 +9916,64 @@ public void loadFlock() addGeneralUseCase(uc); } + public void parseExtendedTransformation(RelationalTransformation tt, String ext) + { + Compiler2 c = new Compiler2(); + BufferedReader br = null; + Vector res = new Vector(); + String s; + boolean eof = false; + File file = new File("output/" + ext + ".qvt"); /* default */ + + BufferedWriter brout = null; + PrintWriter pwout = null; + + File outfile = new File("output/" + ext + "measures.txt"); + + try + { br = new BufferedReader(new FileReader(file)); + brout = new BufferedWriter(new FileWriter(outfile)); + pwout = new PrintWriter(brout); + } + catch (Exception _e) + { System.out.println("!!!! File not found: " + file); + return; + } + + String flockstring = ""; + int noflines = 0; + + while (!eof) + { try { s = br.readLine(); } + catch (IOException _ex) + { System.out.println("!!! Reading failed."); + return; + } + if (s == null) + { eof = true; + break; + } + else if (s.startsWith("--")) { } + else + { flockstring = flockstring + s + " "; } + noflines++; + } + c.nospacelexicalanalysis(flockstring); + + // c.displaylexs(); + RelationalTransformation ttext = c.parse_QVTR(0,c.lexicals.size()-1,entities,types); + if (ttext == null) + { System.err.println("!!!! Invalid QVT-R syntax"); + return; + } + else + { tt.union(ttext); + if (ttext.getExtending() != null) + { parseExtendedTransformation(tt, ttext.getExtending()); } + } + // add the rules of the extended transformation before those of tt. + } + public void loadQVT() { // for (int i = 0; i < entities.size(); i++) @@ -9575,6 +10030,9 @@ else if (s.startsWith("--")) { } { System.err.println("!!!! Invalid QVT-R syntax"); return; } + else if (tt.getExtending() != null) + { parseExtendedTransformation(tt,tt.getExtending()); } + // add the rules of the extended transformation before those of tt. System.out.println("**** Parsed QVT-R: " + tt); tt.typeCheck(types,entities,new Vector(),new Vector()); @@ -9807,7 +10265,7 @@ else if (s.equals("GeneralUseCase:")) } // the generic use case is in its own file public void typeCheckOps() - { System.out.println("Rechecking operations"); + { System.out.println(">> Rechecking operations"); for (int i = 0; i < entities.size(); i++) { Entity ent = (Entity) entities.get(i); ent.typeCheckOps(types,entities); @@ -10150,6 +10608,9 @@ else if (s.startsWith("EntityMapping:")) { EntityMatching em = new EntityMatching(esrc,etrg); System.out.println("Using match: " + sents + " to " + tents); entitymaps.add(em); + AttributeMatching amx = readEntityMapping(br,em); + while (amx != null) + { amx = readEntityMapping(br,em); } } } } catch (IOException _ex) { } @@ -10558,6 +11019,70 @@ else if (s.equals("Activity:")) repaint(); } + public AttributeMatching readEntityMapping(BufferedReader br, EntityMatching em) + { try { String fmap = br.readLine(); + if (fmap.startsWith(" ")) + { String trimemap = fmap.trim(); + int mapsymb = trimemap.indexOf("|"); + if (mapsymb > 0) + { String sf = trimemap.substring(0,mapsymb); + String tf = trimemap.substring(mapsymb + 4, trimemap.length()); + + Compiler2 comp = new Compiler2(); + comp.nospacelexicalanalysis(sf); + Expression src = comp.parseExpression(); + Vector contexts1 = new Vector(); + contexts1.add(em.realsrc); + + Compiler2 comp2 = new Compiler2(); + comp2.nospacelexicalanalysis(tf); + Expression trg = comp2.parseExpression(); + Vector contexts2 = new Vector(); + contexts2.add(em.realtrg); + + if (src != null && trg != null) + { + src.typeCheck(types,entities,contexts1,new Vector()); + trg.typeCheck(types,entities,contexts2,new Vector()); + Vector auxvars = src.allAttributesUsedIn(); + Vector trgvars = trg.allAttributesUsedIn(); + + // System.out.println(">>>> attributes used in " + src + " are: " + auxvars); + + Attribute srcvar = null; + if (auxvars.size() > 0) + { srcvar = (Attribute) auxvars.get(0); } + Attribute trgvar = null; + if (trgvars.size() > 0) + { trgvar = (Attribute) trgvars.get(0); } + else + { System.err.println("!!! ERROR: target of mapping must be an attribute: " + + src + " --> " + trg); + return null; + } + + AttributeMatching newam; + if (("self").equals(src + "")) + { srcvar = new Attribute("self", new Type(em.realsrc), ModelElement.INTERNAL); + newam = new AttributeMatching(src, trgvar, srcvar, auxvars); + // System.out.println(">>> created expression mapping " + src + + // " " + trgvar + " " + srcvar); + } + else if ((src instanceof BasicExpression) && (srcvar + "").equals(src + "")) + { newam = new AttributeMatching(srcvar, trgvar); } + else + { newam = new AttributeMatching(src, trgvar, srcvar, auxvars); } + + em.addMapping(newam); + return newam; + } + } + } + } + catch(Exception _e) { return null; } + return null; + } + public Vector loadThesaurus() { BufferedReader br = null; // BufferedWriter brout = null; @@ -11288,18 +11813,37 @@ else if (me == ent2) // Entity2 repaint(); } + + public void loadComponent() + { String yn = + JOptionPane.showInputDialog("Name of component:"); + if (yn != null) + { loadKM3FromFile(yn + ".km3"); } + Entity component = (Entity) ModelElement.lookupByName(yn,entities); + if (component != null) + { component.addStereotype("external"); } + } public void loadKM3FromFile() - { BufferedReader br = null; + { loadKM3FromFile("mm.km3"); } + + public void loadKM3FromFile(String f) + { Vector oldentities = new Vector(); + oldentities.addAll(entities); + + Vector oldtypes = new Vector(); + oldtypes.addAll(types); + + BufferedReader br = null; Vector res = new Vector(); String s; boolean eof = false; - File file = new File("output/mm.km3"); /* default */ + File file = new File("output/" + f); /* default */ try { br = new BufferedReader(new FileReader(file)); } catch (FileNotFoundException e) - { System.out.println("File not found: " + file); + { System.out.println("File not found: " + f); return; } @@ -11350,15 +11894,23 @@ else if (s.startsWith("--")) { } int delta = 80; // visual displacement int ecount = 0; - for (int i = 0; i < entities.size(); i++) - { Entity enode = (Entity) entities.get(i); + Vector newentities = new Vector(); + newentities.addAll(entities); + newentities.removeAll(oldentities); + + for (int i = 0; i < newentities.size(); i++) + { Entity enode = (Entity) newentities.get(i); addEntity(enode, 20 + (ecount/5)*delta + ((ecount % 5)*delta)/5, 100 + (ecount % 5)*delta); ecount++; } - for (int j = 0; j < types.size(); j++) - { Type tt = (Type) types.get(j); + Vector newtypes = new Vector(); + newtypes.addAll(types); + newtypes.removeAll(oldtypes); + + for (int j = 0; j < newtypes.size(); j++) + { Type tt = (Type) newtypes.get(j); if (tt.isEnumeration()) { RectData rd = new RectData(100*j,20,getForeground(), componentMode, @@ -12609,7 +13161,7 @@ private UseCase parseGeneralUseCase(BufferedReader br) try { line1 = br.readLine(); } catch (IOException e) - { System.err.println("Reading general usecase details failed"); + { System.err.println("!! Reading general usecase details failed"); return null; } StringTokenizer st1 = @@ -12662,7 +13214,7 @@ private UseCase parseGeneralUseCase(BufferedReader br) try { line2 = br.readLine(); } catch (IOException e) - { System.err.println("Reading usecase extends failed"); + { System.err.println("!! Reading usecase extends failed"); return res; } StringTokenizer st2 = @@ -12674,10 +13226,11 @@ private UseCase parseGeneralUseCase(BufferedReader br) UseCase extensionuc = (UseCase) ModelElement.lookupByName(extend,useCases); if (extensionuc == null) - { System.err.println("Extension use case: " + extend + " does not exist"); } + { System.err.println("!! Extension use case: " + extend + " does not exist"); } else { Extend ext = new Extend(res,extensionuc); res.addExtension(ext); + extensionuc.addExtensionOf(res); drawDependency(extensionuc, res, "<>"); } } @@ -12685,7 +13238,7 @@ private UseCase parseGeneralUseCase(BufferedReader br) try { line3 = br.readLine(); } catch (IOException e) - { System.err.println("Reading usecase includes failed"); + { System.err.println("!! Reading usecase includes failed"); return res; } StringTokenizer st3 = @@ -12699,16 +13252,17 @@ private UseCase parseGeneralUseCase(BufferedReader br) if (ucinc != null) { Include ee = new Include(res,ucinc); res.addInclude(ee); + ucinc.addIncludedIn(res); drawDependency(res, ucinc, "<>"); } else - { System.err.println("Included use case: " + include + " does not exist"); } + { System.err.println("!! Included use case: " + include + " does not exist"); } } // System.out.println(line3vals); try { line4 = br.readLine(); } catch (IOException e) - { System.err.println("Reading usecase attributes failed"); + { System.err.println("!! Reading usecase attributes failed"); return res; } StringTokenizer st4 = @@ -12736,7 +13290,7 @@ private UseCase parseGeneralUseCase(BufferedReader br) try { line5 = br.readLine(); } catch (IOException e) - { System.err.println("Reading usecase incremental failed"); + { System.err.println("!! Reading usecase incremental failed"); return null; } // System.out.println("INCREAMENT" + line5); @@ -12828,7 +13382,7 @@ private PreConstraint parseConstraint(BufferedReader br) } PreConstraint cons = new PreConstraint(cond0,cond,succ,line4vals,orderedBy); - // System.out.println("Retrived constraint: " + cons); + System.out.println(">> Retrieved constraint: " + cons); return cons; } // and line5 = use case @@ -13218,9 +13772,53 @@ public String generateDbi(Vector operations) " }\n}\n"; } - public void generateAndroidDbi(Vector operations, PrintWriter out) - { Entity e0 = (Entity) entities.get(0); - e0.androidDbi(out); + public void generateAndroidDbi(Vector ents, Vector operations, PrintWriter out) + { out.println("package com.example.app;"); + out.println(); + out.println(); + out.println("import android.content.Context;"); + out.println("import android.database.sqlite.SQLiteDatabase;"); + out.println("import android.database.sqlite.SQLiteOpenHelper;"); + out.println("import android.content.ContentValues;"); + out.println("import android.database.Cursor;"); + out.println("import java.util.List;"); + out.println("import java.util.ArrayList;"); + out.println(); + out.println("public class Dbi extends SQLiteOpenHelper"); + out.println("{ SQLiteDatabase database;"); + out.println(" private static final String DBNAME = \"app.db\";"); + out.println(" private static final int DBVERSION = 1;"); + out.println(); + + String createCode = ""; + for (int i = 0; i < ents.size(); i++) + { Entity e0 = (Entity) ents.get(i); + e0.androidDbiDeclarations(out); + String ent = e0.getName(); + createCode = createCode + "db.execSQL(" + ent + "_CREATE_SCHEMA);\n "; + } + + out.println(" public Dbi(Context context)"); + out.println(" { super(context, DBNAME, null, DBVERSION); }"); + out.println(); + out.println(" @Override"); + out.println(" public void onCreate(SQLiteDatabase db)"); + out.println(" { " + createCode + " }"); + out.println(); + + for (int i = 0; i < ents.size(); i++) + { Entity e0 = (Entity) ents.get(i); + e0.androidDbiOperations(out); + } + + out.println(" // @Override"); + out.println(" public void onDestroy()"); + out.println(" { // super.onDestroy();"); + out.println(" database.close(); }"); + out.println(); + out.println(" public void onUpgrade(SQLiteDatabase d, int x, int y) {}"); + out.println(); + out.println("}"); } public String generateJspDbi(Vector operations) @@ -14653,6 +15251,163 @@ else if (salternatives.contains(te)) { } synthesiseTransformations(modmatch,entities,thesaurus); } + public void synthesiseFromTL(Vector thesaurus) + { if (tlspecification != null) + { synthesiseTransformations(tlspecification,entities,thesaurus); } + else + { System.err.println("!! No TL specification loaded"); } + } + + public void mapTL2UMLRSDS(Vector thesaurus) + { if (tlspecification != null) + { synthesiseTransformationsUMLRSDS(tlspecification,entities,thesaurus); + Vector pregens = new Vector(); + Vector preassocs = new Vector(); + + BufferedReader br = null; + Vector res = new Vector(); + String s; + boolean eof = false; + File file = new File("output/umlrsdscode.txt"); /* default */ + + try + { br = new BufferedReader(new FileReader(file)); } + catch (FileNotFoundException e) + { System.out.println("File not found: " + file); + return; + } + + + String xmlstring = ""; + int linecount = 0; + + while (!eof) + { try { s = br.readLine(); } + catch (IOException e) + { System.out.println("Reading failed."); + return; + } + if (s == null) + { eof = true; + break; + } + else if (s.startsWith("--")) { } + else + { xmlstring = xmlstring + s + " "; } + linecount++; + } + + + Compiler2 comp = new Compiler2(); + comp.nospacelexicalanalysis(xmlstring); + UseCase uc = comp.parseKM3UseCase(entities,types,pregens,preassocs); + if (uc != null) + { addGeneralUseCase(uc); } + } + else + { System.err.println("!! No TL specification loaded"); } + } + + public void checkTLmodel() + { if (tlspecification != null) + { ModelSpecification modelspec = new ModelSpecification(); + + BufferedReader br = null; + Vector res = new Vector(); + String s; + boolean eof = false; + File file = new File("output/out.txt"); /* default location of model */ + + try + { br = new BufferedReader(new FileReader(file)); } + catch (FileNotFoundException e) + { System.out.println("File not found: " + file); + return; + } + + while (!eof) + { try { s = br.readLine(); } + catch (IOException e) + { System.err.println("!! Reading failed."); + return; + } + + if (s == null) + { eof = true; + break; + } + else if (s.startsWith("--")) { } + else if (s.trim().length() == 0) { } + else + { String str = s.trim(); + String[] strs = str.split(" "); + if (strs.length == 3 && ":".equals(strs[1]) && strs[2].indexOf(".") < 0) // obj : class + { String obj = strs[0]; + String ename = strs[2]; + System.out.println(">>> object " + obj + " of class " + ename); + Entity ent = (Entity) ModelElement.lookupByName(ename,entities); + if (ent == null) + { System.err.println("!! No class called " + ename); } + else + { ObjectSpecification objspec = new ObjectSpecification(obj,ename); + objspec.setEntity(ent); + modelspec.addObject(objspec); + } + } + else if (strs.length == 3 && "=".equals(strs[1])) // x.prop = val + { String lft = strs[0]; + int idx = lft.indexOf("."); + if (idx > 0) + { String x = lft.substring(0,idx); + String prop = lft.substring(idx+1,lft.length()); + int ind2 = str.indexOf("="); + String val = str.substring(ind2 + 1, str.length()); + val = val.trim(); + System.out.println("LINE: " + x + "." + prop + " = " + val); + ObjectSpecification objspec = modelspec.getObject(x); + if (objspec == null) + { System.err.println("!! ERROR: no object called " + x); } + else + { objspec.addAttribute(prop,val); } + } + } + else if (strs.length == 3 && ":".equals(strs[1]) && strs[2].indexOf(".") > 0) // val : x.prop + { String lft = strs[0]; // value/object to be added + String rgt = strs[2]; + int indx2 = rgt.indexOf("."); + if (indx2 > 0) + { String xx = rgt.substring(0,indx2); + String prop = rgt.substring(indx2+1,rgt.length()); + String val = lft.trim(); + System.out.println("LINE: " + val + " : " + xx + "." + prop); + ObjectSpecification xspec = modelspec.getObject(xx); + if (xspec == null) + { System.err.println("!! ERROR: no object called " + xx); } + else + { ObjectSpecification valspec = modelspec.getObject(val); + if (valspec != null) + { xspec.addAttributeElement(prop,valspec); } + else + { xspec.addAttributeElement(prop,val); } + } + } + } + else + { System.err.println("!!! Unrecognised line: " + str); } + } + // file.close(); + } + System.out.println(">>> Read model " + modelspec); + tlspecification.checkModel(modelspec); + } + else + { System.err.println("!! ERROR: no TL specification"); } + } + + + + + public void ontologicalSimilarity(Vector thesaurus) { Vector sources = getSourceEntities(); @@ -16841,10 +17596,22 @@ private void synthesiseTransformations(ModelMatching selected, Vector originalen { selected.removeInvalidMatchings(); selected.copySuperclassMatchings(thesaurus,originalentities); selected.checkBidirectionalAssociationConsistency(); - selected.checkEntityMapCompleteness(originalentities); + Vector unusedentities = selected.checkEntityMapCompleteness(originalentities); - Vector corrpatts = selected.analyseCorrelationPatterns(originalentities); + Vector corrpatts = selected.analyseCorrelationPatterns(originalentities,types); + Vector sources = Entity.sourceEntities(originalentities); + Vector unusedtargets = selected.unusedTargetEntities(originalentities); + + selected.checkValidity(unusedtargets,entities,sources,thesaurus); + + String yn = + JOptionPane.showInputDialog("Check that all target features are used (y or n)?:"); + + if (yn != null && yn.equals("y")) + { selected.checkTargetFeatureCompleteness(entities,sources,thesaurus); } + selected.removeSpuriousMatchings(); + selected.addFlagVariables(corrpatts); System.out.println("----------Correlation patterns are: ----------------------------"); System.out.println(); @@ -16856,6 +17623,14 @@ private void synthesiseTransformations(ModelMatching selected, Vector originalen System.out.println("----------------------------------------------------------------"); + try + { PrintWriter fout = new PrintWriter( + new BufferedWriter( + new FileWriter("output/forward.tl"))); + fout.println(selected); + fout.close(); + } catch (Exception _except) { } + try { PrintWriter cout = new PrintWriter( new BufferedWriter( @@ -16878,13 +17653,13 @@ private void synthesiseTransformations(ModelMatching selected, Vector originalen Vector benames = new Vector(); Vector bconvs = selected.boolEnumConversions(benames); - System.out.println(">>> boolean-enumeration conversions are: " + bconvs + " " + benames); + // System.out.println(">>> boolean-enumeration conversions are: " + bconvs + " " + benames); Vector beFunctions = selected.booleanEnumConversionFunctions(bconvs,benames); Vector ebnames = new Vector(); Vector ebconvs = selected.enumBoolConversions(ebnames); - System.out.println(">>> enumeration-boolean conversions are: " + ebconvs + " " + - ebnames); + // System.out.println(">>> enumeration-boolean conversions are: " + ebconvs + " " + + // ebnames); Vector ebFunctions = selected.enumBooleanConversionFunctions(ebconvs,ebnames); cout.println("/* QVT-R transformation: */"); @@ -16940,21 +17715,38 @@ private void synthesiseTransformations(ModelMatching selected, Vector originalen cout.println(selected.atlTransformation(types)); + Vector ecfuncsetl = selected.enumConversionFunctionsETL(enumconvs,thesaurus); + Vector esfuncsetl = selected.enumStringConversionFunctionsETL(enumstringconversions,thesaurus); + Vector sefuncsetl = selected.stringEnumConversionFunctionsETL(stringenumconversions,thesaurus); + EtlModule etlmod = selected.etlTransformation(types,bconvs,benames,ebconvs,ebnames); + etlmod.addOperations(ecfuncsetl); + etlmod.addOperations(esfuncsetl); + etlmod.addOperations(sefuncsetl); + cout.println(etlmod + ""); + cout.close(); } catch (Exception ex) { ex.printStackTrace(); } + ModelMatching inv = selected.invert(); + + try + { PrintWriter revout = new PrintWriter( + new BufferedWriter( + new FileWriter("output/reverse.tl"))); + revout.println(inv); + revout.close(); + } catch (Exception _except) { } try { PrintWriter rout = new PrintWriter( new BufferedWriter( new FileWriter("output/reverse.txt"))); - ModelMatching inv = selected.invert(); rout.println("----------------------- Reverse map is \n" + inv); - Vector enumconvs = selected.enumConversions(); - Vector ecfuncs = selected.enumConversionFunctions(enumconvs,thesaurus); + Vector enumconvs = inv.enumConversions(); + Vector ecfuncs = inv.enumConversionFunctions(enumconvs,thesaurus); Vector stringenumconversions = inv.stringEnumConversions(); // System.out.println(">>> String-enumeration conversions are: " + stringenumconversions); @@ -17027,6 +17819,105 @@ private void synthesiseTransformations(ModelMatching selected, Vector originalen rout.println(inv.atlTransformation(types)); + Vector recfuncsetl = inv.enumConversionFunctionsETL(enumconvs,thesaurus); + EtlModule retlmod = inv.etlTransformation(types,invbconvs,benamesinv,invebconvs,ebnamesinv); + retlmod.addOperations(recfuncsetl); + rout.println(retlmod + ""); + + rout.close(); + } + catch (Exception ex) + { ex.printStackTrace(); } + } + + private void synthesiseTransformationsUMLRSDS(ModelMatching selected, Vector originalentities, + Vector thesaurus) + { System.out.println("----------------------------------------------------------------"); + + for (int i = 0; i < entities.size(); i++) + { Entity ee = (Entity) entities.get(i); + Attribute puk = ee.getPrincipalPK(); + if (puk == null) + { ee.addPrimaryKey(ee.getName().toLowerCase() + "Id"); } + } + + try + { PrintWriter cout = new PrintWriter( + new BufferedWriter( + new FileWriter("output/umlrsdscode.txt"))); + + PrintWriter qout = new PrintWriter( + new BufferedWriter( + new FileWriter("output/qvtrcode.txt"))); + + Vector enumconvs = selected.enumConversions(); + // System.out.println(">>> Enumeration conversions are: " + enumconvs); + Vector ecfuncs = selected.enumConversionFunctions(enumconvs,thesaurus); + // System.out.println(">>> Enumeration conversion functions are: " + ecfuncs); + + Vector stringenumconversions = selected.stringEnumConversions(); + // System.out.println(">>> String-enumeration conversions are: " + stringenumconversions); + Vector seFunctions = selected.stringEnumConversionFunctions(stringenumconversions); + + Vector enumstringconversions = selected.enumStringConversions(); + // System.out.println(">>> enumeration-String conversions are: " + enumstringconversions); + Vector esFunctions = selected.enumStringConversionFunctions(enumstringconversions); + + Vector benames = new Vector(); + Vector bconvs = selected.boolEnumConversions(benames); + // System.out.println(">>> boolean-enumeration conversions are: " + bconvs + " " + benames); + Vector beFunctions = selected.booleanEnumConversionFunctions(bconvs,benames); + + Vector ebnames = new Vector(); + Vector ebconvs = selected.enumBoolConversions(ebnames); + // System.out.println(">>> enumeration-boolean conversions are: " + ebconvs + " " + + // ebnames); + Vector ebFunctions = selected.enumBooleanConversionFunctions(ebconvs,ebnames); + + cout.println(selected.umlrsdsTransformation(enumconvs,stringenumconversions, + enumstringconversions,bconvs,ebconvs)); + + qout.println(selected.qvtBxTransformation(enumconvs,stringenumconversions, + enumstringconversions,bconvs,ebconvs)); + + cout.close(); + qout.close(); + } + catch (Exception ex) + { ex.printStackTrace(); } + + ModelMatching inv = selected.invert(); + + try + { PrintWriter rout = new PrintWriter( + new BufferedWriter( + new FileWriter("output/reverseumlrsds.txt"))); + + Vector enumconvs = inv.enumConversions(); + Vector ecfuncs = inv.enumConversionFunctions(enumconvs,thesaurus); + + Vector stringenumconversions = inv.stringEnumConversions(); + // System.out.println(">>> String-enumeration conversions are: " + stringenumconversions); + Vector seFunctions = inv.stringEnumConversionFunctions(stringenumconversions); + + Vector enumstringconversions = inv.enumStringConversions(); + // System.out.println(">>> enumeration-String conversions are: " + enumstringconversions); + Vector esFunctions = inv.enumStringConversionFunctions(enumstringconversions); + + Vector benamesinv = new Vector(); + Vector invbconvs = inv.boolEnumConversions(benamesinv); + // System.out.println(">>> boolean-enumeration conversions are: " + bconvs); + Vector invbeFunctions = inv.booleanEnumConversionFunctions(invbconvs,benamesinv); + + Vector ebnamesinv = new Vector(); + Vector invebconvs = inv.enumBoolConversions(ebnamesinv); + // System.out.println(">>> enumeration-boolean conversions are: " + ebconvs); + Vector invebFunctions = inv.enumBooleanConversionFunctions(invebconvs,ebnamesinv); + + + rout.println(inv.umlrsdsTransformation(enumconvs,stringenumconversions, + enumstringconversions,invbconvs,invebconvs)); + rout.close(); } catch (Exception ex) diff --git a/UmlTool.java b/UmlTool.java index 8baf0471..e0c1d159 100644 --- a/UmlTool.java +++ b/UmlTool.java @@ -260,13 +260,41 @@ public UmlTool() loadMTMenu.add(loadETLMI); JMenuItem loadQVTMI = - new JMenuItem("Load QVT",openIcon); + new JMenuItem("Load QVT-R",openIcon); loadQVTMI.addActionListener(this); loadQVTMI.setToolTipText( - "Load QVT-R module from test.qvt"); + "Load QVT-R module from mm.qvt"); // loadEcoreMI.setMnemonic(KeyEvent.VK_L); loadMTMenu.add(loadQVTMI); + JMenuItem loadTLMI = + new JMenuItem("Load TL",openIcon); + loadTLMI.addActionListener(this); + loadTLMI.setToolTipText( + "Load TL module from file.tl"); + // loadEcoreMI.setMnemonic(KeyEvent.VK_L); + loadMTMenu.add(loadTLMI); + + JMenuItem loadCSTLMI = + new JMenuItem("Load CSTL",openIcon); + loadCSTLMI.addActionListener(this); + loadCSTLMI.setToolTipText( + "Load CSTL module from file.cstl"); + // loadEcoreMI.setMnemonic(KeyEvent.VK_L); + loadMTMenu.add(loadCSTLMI); + + JMenuItem tl2umlrsds = + new JMenuItem("Map TL to bx"); + tl2umlrsds.addActionListener(this); + fileMenu.add(tl2umlrsds); + + JMenuItem checkTL = + new JMenuItem("Check model wrt TL"); + checkTL.addActionListener(this); + fileMenu.add(checkTL); + + fileMenu.addSeparator(); + JMenuItem loadGenericMI = new JMenuItem("Load generic use case",openIcon); loadGenericMI.addActionListener(this); @@ -377,7 +405,7 @@ public UmlTool() //Build second menu in the menu bar. JMenu createMenu = new JMenu("Create"); createMenu.setToolTipText( - "Create classes and invariants"); + "Create classes, features and invariants"); createMenu.setMnemonic(KeyEvent.VK_C); menuBar.add(createMenu); @@ -529,6 +557,12 @@ public UmlTool() guiMI.addActionListener(this); createMenu.add(guiMI); + JMenuItem componentMI = new JMenuItem("Component"); + componentMI.addActionListener(this); + createMenu.add(componentMI); + + createMenu.addSeparator(); + // JMenuItem transMenu = new JMenu("Event flow"); // createMenu.add(transMenu); @@ -903,8 +937,14 @@ public UmlTool() gasimilarity.addActionListener(this); flatten.add(gasimilarity); + JMenuItem fromloadedTL = + new JMenuItem("From loaded TL"); + fromloadedTL.addActionListener(this); + flatten.add(fromloadedTL); + synthMenu.addSeparator(); + JMenuItem normalise = new JMenuItem("Form Contrapositives"); normalise.addActionListener(this); @@ -1029,6 +1069,15 @@ public UmlTool() // javaMenu.setEnabled(false); buildMenu.add(pyMenu); + buildMenu.addSeparator(); + + JMenuItem cstlGenerator = new JMenuItem("Use CSTL specification"); + cstlGenerator.addActionListener(this); + buildMenu.add(cstlGenerator); + + + buildMenu.addSeparator(); + JMenu webMI = new JMenu("Web System"); buildMenu.add(webMI); @@ -1051,6 +1100,10 @@ public UmlTool() buildMenu.add(androidMI); androidMI.addActionListener(this); + JMenuItem iosMI = new JMenuItem("iOS system"); + buildMenu.add(iosMI); + iosMI.addActionListener(this); + buildMenu.addSeparator(); JMenu webserv = new JMenu("Web Service"); @@ -1236,6 +1289,8 @@ else if (label.equals("Requirements")) } else if (label.equals("GUI")) { buildGUI(); } + else if (label.equals("Component")) + { ucdArea.loadComponent(); } else if (label.equals("OCL")) { ucdArea.printOCL(); } else if (label.equals("Type")) @@ -1245,7 +1300,7 @@ else if (label.equals("Type")) { return; } if (tname.equals("int") || tname.equals("String") || tname.equals("long") || tname.equals("double") || tname.equals("boolean")) - { System.err.println("Cannot redefine inbuilt type!"); + { System.err.println("ERROR: Cannot redefine inbuilt type!"); return; } String values = @@ -1399,6 +1454,14 @@ else if (label.equals("Load *.km3")) { ucdArea.loadKM3FromFile(); saved = true; } + else if (label.equals("Load TL")) + { ucdArea.loadTL(); + // saved = true; + } + else if (label.equals("Load CSTL")) + { ucdArea.loadCSTL(); + // saved = true; + } else if (label.equals("Load standard ATL")) { ucdArea.loadATL(); // saved = true; @@ -1413,7 +1476,7 @@ else if (label.equals("Load Flock")) { ucdArea.loadFlock(); // saved = true; } - else if (label.equals("Load QVT")) + else if (label.equals("Load QVT-R")) { ucdArea.loadQVT(); // saved = true; } @@ -1651,6 +1714,8 @@ else if (label.equals("Generate C code")) catch (IOException ex) { System.out.println("Error generating C UI"); } } + else if (label.equals("Use CSTL specification")) + { ucdArea.applyCSTLSpecification(); } else if (label.equals("Generate Python")) { ucdArea.saveModelToFile("output/model.txt"); @@ -1712,7 +1777,7 @@ else if (label.equals("JSP style")) new TextDisplay("Web System code","output/jsps.txt"); } else if (label.equals("Android system")) - { File file = new File("output/layout.xml"); + { File file = new File("output/MainActivity.java"); try { PrintWriter out = new PrintWriter( new BufferedWriter( @@ -1723,8 +1788,10 @@ else if (label.equals("Android system")) catch (IOException ex) { System.out.println("Error generating Android System"); } - new TextDisplay("Android System code","output/layout.xml"); + new TextDisplay("Android System code","output/MainActivity.java"); } + else if (label.equals("iOS system")) + { ucdArea.generateIOSApp(); } else if (label.equals("J2EE style")) { File file = new File("output/j2ees.txt"); try @@ -1944,6 +2011,18 @@ else if (label.equals("Composite score")) { Vector t = ucdArea.loadThesaurus(); ucdArea.refinementScore(t); } + else if (label.equals("From loaded TL")) + { Vector t = ucdArea.loadThesaurus(); + ucdArea.synthesiseFromTL(t); + } + else if (label.equals("Map TL to bx")) + { Vector t = ucdArea.loadThesaurus(); + ucdArea.mapTL2UMLRSDS(t); + } + else if (label.equals("Check model wrt TL")) + { + ucdArea.checkTLmodel(); + } else if (label.equals("Use Case Dependencies")) { ucdArea.showUCDependencies(); } else if (label.equals("Form Contrapositives")) diff --git a/UnaryExpression.java b/UnaryExpression.java index 8262abcc..38c369c3 100644 --- a/UnaryExpression.java +++ b/UnaryExpression.java @@ -24,6 +24,15 @@ public UnaryExpression(String op, Expression arg) argument = arg; } + public UnaryExpression(BasicExpression be) + { // obj.op() becomes obj->op() + + argument = ((BasicExpression) be).getObjectRef(); + operator = "->" + be.getData(); + type = be.getType(); + elementType = be.getElementType(); + } + public String getOperator() { return operator; } @@ -104,6 +113,12 @@ else if ("->toLong".equals(operator)) public void setPre() { argument.setPre(); } + public Expression removePrestate() + { UnaryExpression res = (UnaryExpression) clone(); + res.argument = argument.removePrestate(); + return res; + } + public Expression determinate() { Expression res = argument.determinate(); @@ -153,7 +168,7 @@ public Vector splitToCond0Cond1(Vector conds, Vector qvars, Vector lvars, Vector } // The following turns x : e & P & l = g & Q into [x,P,l,Q] in allvars - public Vector splitToCond0Cond1Pred(Vector conds, Vector pars, Vector qvars, Vector lvars, Vector allvars) + public Vector splitToCond0Cond1Pred(Vector conds, Vector pars, Vector qvars, Vector lvars, Vector allvars, Vector allpreds) { Expression cond0 = (Expression) conds.get(0); Expression cond1 = (Expression) conds.get(1); Vector res = new Vector(); @@ -167,7 +182,8 @@ public Vector splitToCond0Cond1Pred(Vector conds, Vector pars, Vector qvars, Vec res.add(cond0); res.add(c1); allvars.add(this); - System.out.println("Added condition: " + this); + allpreds.add(this); + System.out.println(">>>>> Added condition: " + this); return res; } @@ -1114,6 +1130,9 @@ public Vector innermostEntities() public Vector innermostVariables() { return argument.innermostVariables(); } + public Vector allAttributesUsedIn() + { return argument.allAttributesUsedIn(); } + public Vector allPreTerms() { return argument.allPreTerms(); } @@ -1284,7 +1303,7 @@ else if (type == null) return res; } - if (operator.equals("-") || operator.equals("->abs")) + if (operator.equals("-") || operator.equals("+") || operator.equals("->abs")) { type = argument.type; elementType = argument.elementType; if (type == null) @@ -1322,6 +1341,15 @@ else if (type == null) return res; } + if (operator.equals("->allInstances")) + { type = new Type("Sequence",null); + elementType = argument.getElementType(); + type.setElementType(elementType); + multiplicity = ModelElement.MANY; + modality = argument.modality; + return res; + } + if (operator.equals("->flatten")) { type = argument.type; if (argument.isMultiple() && type.elementType != null) @@ -1340,6 +1368,14 @@ else if (type == null) return res; } + if (operator.equals("->keys")) + { type = new Type("Set",null); + elementType = new Type("String",null); + type.setElementType(elementType); + multiplicity = ModelElement.MANY; + return res; + } + if (operator.equals("->closure")) { BasicExpression closured = (BasicExpression) argument; // BasicExpression arg = (BasicExpression) closured.getObjectRef(); @@ -1371,7 +1407,7 @@ else if (type == null) } } - if (operator.equals("->asSequence") || operator.equals("->sort")) + if (operator.equals("->asSequence") || operator.equals("->sort") || operator.equals("->values")) { type = new Type("Sequence",null); elementType = argument.elementType; type.setElementType(elementType); @@ -1463,8 +1499,8 @@ public int minModality() public boolean isMultiple() { if (operator.equals("->subcollections") || - operator.equals("->closure") || operator.equals("->asSet") || - operator.equals("->flatten") || operator.equals("->characters") || + operator.equals("->closure") || operator.equals("->asSet") || operator.equals("->values") || + operator.equals("->flatten") || operator.equals("->characters") || operator.equals("->keys") || operator.equals("->asSequence") || operator.equals("->sort")) { return true; } @@ -1517,6 +1553,13 @@ public String queryForm(java.util.Map env, boolean local) return "(" + qf + ").size()"; } + if (operator.equals("->allInstances")) + { if (argument.umlkind == CLASSID && + (argument instanceof BasicExpression) && + ((BasicExpression) argument).arrayIndex == null) + { return cont + "." + qf.toLowerCase() + "s"; } + } // and for other languages + if (operator.equals("->display")) { return "true"; } @@ -1532,9 +1575,11 @@ else if (argument.type != null) return "false"; } - if (operator.equals("->asSequence")) { return qf; } + if (operator.equals("->asSequence")) + { return qf; } // but maps cannot be converted - if (operator.equals("->sqr")) { return "((" + qf + ")*(" + qf + "))"; } + if (operator.equals("->sqr")) + { return "((" + qf + ")*(" + qf + "))"; } if (operator.equals("->flatten")) { if (Type.isSequenceType(argument.type)) @@ -1542,7 +1587,7 @@ else if (argument.type != null) else if (Type.isSetType(argument.type)) { return "Set.unionAll(" + qf + ")"; } return qf; - } // but only goes one level down. + } // but only goes one level down. Not for maps if (operator.equals("->isInteger")) { return "Set.isInteger(" + qf + ")"; } @@ -1645,6 +1690,10 @@ else if (data.equals("notEmpty")) else if (data.equals("reverse") || data.equals("sort") || data.equals("asSet")) { return "Set." + data + "(" + pre + ")"; } + else if (data.equals("keys")) + { return pre + ".keySet()"; } + else if (data.equals("values")) + { return pre + ".values()"; } else if (data.equals("closure")) { String rel = ((BasicExpression) argument).data; Expression arg = ((BasicExpression) argument).objectRef; @@ -1851,6 +1900,10 @@ else if (Type.isPrimitiveType(et)) } else if (data.equals("asSet") || data.equals("asSequence")) { return "Set." + data + "(" + pre + ")"; } + else if (data.equals("keys")) + { return pre + ".keySet()"; } + else if (data.equals("values")) + { return pre + ".values()"; } else if (data.equals("closure")) { String rel = ((BasicExpression) argument).data; Expression arg = ((BasicExpression) argument).objectRef; @@ -2050,6 +2103,10 @@ else if (Type.isPrimitiveType(et)) } else if (data.equals("asSet") || data.equals("asSequence")) { return "Ocl." + data + "(" + pre + ")"; } + else if (data.equals("keys")) + { return pre + ".keySet()"; } + else if (data.equals("values")) + { return pre + ".values()"; } else if (data.equals("closure")) { String rel = ((BasicExpression) argument).data; Expression arg = ((BasicExpression) argument).objectRef; @@ -2173,7 +2230,8 @@ public String queryFormCSharp(java.util.Map env, boolean local) if (operator.equals("->oclIsUndefined")) { return "(" + qf + " == null)"; } - if (operator.equals("->sqr")) { return "((" + qf + ")*(" + qf + "))"; } + if (operator.equals("->sqr")) + { return "((" + qf + ")*(" + qf + "))"; } if (operator.equals("->flatten")) { if (Type.isSequenceType(argument.type)) @@ -2248,6 +2306,10 @@ else if (data.equals("notEmpty")) else if (data.equals("reverse") || data.equals("sort") || data.equals("asSet")) { return "SystemTypes." + data + "(" + pre + ")"; } + else if (data.equals("keys")) + { return "SystemTypes.mapKeys(" + pre + ")"; } + else if (data.equals("values")) + { return "SystemTypes.mapValues(" + pre + ")"; } else if (data.equals("closure") && (argument instanceof BasicExpression)) { String rel = ((BasicExpression) argument).data; Expression arg = ((BasicExpression) argument).objectRef; @@ -2431,6 +2493,10 @@ else if (data.equals("notEmpty")) else if (data.equals("reverse") || data.equals("sort") || data.equals("asSet") || data.equals("asSequence")) { return "UmlRsdsLib<" + celtype + ">::" + data + "(" + pre + ")"; } + else if (data.equals("keys")) + { return "UmlRsdsLib::keys(" + pre + ")"; } + else if (data.equals("values")) + { return "UmlRsdsLib<" + celtype + ">::values(" + pre + ")"; } else if (data.equals("closure") && (argument instanceof BasicExpression)) { String rel = ((BasicExpression) argument).data; Expression arg = ((BasicExpression) argument).objectRef; @@ -2494,7 +2560,7 @@ else if (et.isEntity()) else { return "UmlRsdsLib::" + data + "(" + pre + ")"; } // return qf + ".get(0)"; - } + } // keys, values public BExpression bqueryForm(java.util.Map env) { BExpression pre = argument.bqueryForm(env); @@ -2997,9 +3063,9 @@ public String toSQL() if (data.equals("size")) // also strings { return "CARD(" + pre + ")"; } if (data.equals("abs") || data.equals("sqr") || - data.equals("sqrt") || data.equals("max") || data.equals("floor") || - data.equals("min") || data.equals("exp") || data.equals("log") || - data.equals("sin") || data.equals("cos") || data.equals("tan")) + data.equals("sqrt") || data.equals("max") || data.equals("floor") || + data.equals("min") || data.equals("exp") || data.equals("log") || + data.equals("sin") || data.equals("cos") || data.equals("tan")) { op = data.toUpperCase(); return op + "(" + pre + ")"; } @@ -3264,7 +3330,12 @@ public String cg(CGSpec cgs) args.add(argument.cg(cgs)); CGRule r = cgs.matchedUnaryExpressionRule(this,etext); if (r != null) - { return r.applyRule(args); } + { String res = r.applyRule(args); + if (needsBracket) + { return "(" + res + ")"; } + else + { return res; } + } return etext; } diff --git a/UseCase.java b/UseCase.java index bfa5c583..733dbf0c 100644 --- a/UseCase.java +++ b/UseCase.java @@ -31,7 +31,10 @@ public class UseCase extends ModelElement Vector extend = new Vector(); // Extend objects pointing to extension use cases // should be called "extensions", it is not the "extend" in the UML metamodel + Vector extensionOf = new Vector(); // The UseCases which this extends Vector include = new Vector(); // Include objects of this use case + Vector includedIn = new Vector(); // The UseCases which include this + boolean generic = false; boolean derived = false; UseCase superclass = null; @@ -52,7 +55,10 @@ public UseCase(String nme, Entity e) classifier.addStereotype("derived"); operation = new BehaviouralFeature(nme); operation.addStereotype("derived"); + operation.setResultType(new Type("void",null)); operation.addStereotype("auxiliary"); + operation.setPrecondition(new BasicExpression(true)); + operation.setPostcondition(new BasicExpression(true)); classifier.addOperation(operation); } @@ -64,8 +70,12 @@ public UseCase(String nme) classifier.addStereotype("derived"); BehaviouralFeature bf = new BehaviouralFeature(nme); bf.addStereotype("derived"); + bf.setResultType(new Type("void",null)); classifier.addOperation(bf); operation = bf; + operation.addStereotype("auxiliary"); + operation.setPrecondition(new BasicExpression(true)); + operation.setPostcondition(new BasicExpression(true)); } public void setResultType(Type et) @@ -86,6 +96,15 @@ public Type getResultType() public Type getElementType() { return elementType; } + public Attribute getResultParameter() + { if (resultType != null) + { Attribute res = new Attribute("result", resultType, ModelElement.INTERNAL); + res.setElementType(elementType); + return res; + } + return null; + } + public Entity getClassifier() { return classifier; } @@ -105,6 +124,13 @@ public void setName(String nme) classifier.setName(ename); } } + + public void setEntity(Entity e) + { ent = e; } + // Associated entity: use case only updates features of ent. + + public Entity getEntity() + { return ent; } public int ruleCount() { return orderedPostconditions.size(); } @@ -467,6 +493,28 @@ public Vector allPreTerms() public Vector getPreconditions() { return preconditions; } + public void addExtensionOf(UseCase base) + { extensionOf.add(base); } + + public void removeExtensionOf(UseCase base) + { extensionOf.remove(base); } + + public void addIncludedIn(UseCase base) + { includedIn.add(base); } + + public void removeIncludedIn(UseCase base) + { includedIn.remove(base); } + + public Vector cwr(Vector assocs) + { Vector res = new Vector(); + for (int i = 0; i < orderedPostconditions.size(); i++) + { ConstraintOrGroup cns = + (ConstraintOrGroup) orderedPostconditions.get(i); + res = VectorUtil.union(res,cns.cwr(assocs)); + } + return res; + } + public Vector wr(Vector assocs) { Vector res = new Vector(); for (int i = 0; i < orderedPostconditions.size(); i++) @@ -487,6 +535,17 @@ public Vector readFrame() return res; } + public Entity findEntity(Vector entities, Vector assocs) + { Vector readents = new Vector(); + Vector wrents = new Vector(); + classDependencies(entities,assocs,readents,wrents); + if (wrents.size() > 0) + { ent = (Entity) wrents.get(0); + return ent; + } + return null; + } + public void classDependencies(Vector entities, Vector assocs, Vector readents, Vector writtenents) { // Computes which entities are read, and which are written by the use case Vector wrf = wr(assocs); @@ -524,7 +583,8 @@ public void classDependencies(Vector entities, Vector assocs, Vector readents, V System.out.println(""); System.out.println("Use case " + this + " reads entities: " + readents); System.out.println("Use case " + this + " writes entities: " + writtenents); - System.out.println(""); + System.out.println("Associated entity: " + ent + " should be the only written entity."); + System.out.println(); } public void addStatement(Statement stat) @@ -536,6 +596,15 @@ public void addExtension(Extend ext) extend.add(ext); } + public Vector extensionUseCases() + { Vector res = new Vector(); + for (int i = 0; i < extend.size(); i++) + { Extend ext = (Extend) extend.get(i); + res.add(ext.extension); + } + return res; + } + public void addInclude(Include ext) { // ext.addition /: uc1.extend.extension for any other uc1 include.add(ext); @@ -684,8 +753,8 @@ public void analyseConstraints(Vector types, Vector entities, Vector assocs) // JOptionPane.showMessageDialog(null, "Constraint " + inv + "\n is of type 1", // "Constraint analysis", // JOptionPane.INFORMATION_MESSAGE); - System.out.println("Implementation by bounded loop.\n" + - "Syntactic check for confluence & correctness."); + System.out.println(">-> Implementation by bounded loop.\n" + + ">-> Syntactic check for confluence & correctness."); constraintType = 1; inv.setConstraintKind(1); } @@ -695,7 +764,7 @@ public void analyseConstraints(Vector types, Vector entities, Vector assocs) if (owner == null) { constraintType = 0; inv.setConstraintKind(0); - System.out.println("Owner is null; bounded loop will be used."); + System.out.println(">-> Owner is null; bounded loop will be used."); if (oldConstraintType > 1) { System.out.println("But a bounded loop may not be sufficient!"); } } @@ -709,7 +778,7 @@ public void analyseConstraints(Vector types, Vector entities, Vector assocs) } Vector res = allPreTerms(); - System.out.println("All pre-terms: " + res); + System.out.println(">-> All pre-terms: " + res); } // no analysis of groups? @@ -931,6 +1000,33 @@ else if (cc.hasAntecedent()) } } + public void identifyInputsOutputs(Vector assocs) + { // assume analyseDependencies has already been done, and derived = false + + Vector newparms = new Vector(); + newparms.addAll(parameters); + + Vector inputs = new Vector(); // written and read + Vector outputs = new Vector(); // only written + + for (int i = 0; i < orderedPostconditions.size(); i++) + { ConstraintOrGroup cc = (ConstraintOrGroup) orderedPostconditions.get(i); + Vector ccrd = cc.readFrame(); + Vector ccwr = cc.wr(assocs); + DataDependency dd = cc.getDataFlows(); + System.out.println("Data flows for " + cc + " are: " + dd); + // DataDependency dd = cc.rhsDataDependency(); + System.out.println(">> read in constraint " + i + " = " + ccrd); + System.out.println(">> written in constraint " + i + " = " + ccwr); + System.out.println(">> Data-dependencies: " + dd); + } + + // owner.setActivity(stat); + newparms.addAll(ownedAttribute); // and result + System.out.println(">>> Parameters = " + newparms); + // System.out.println("Type-checking " + stat + " with " + newparms); + } + public UseCase instantiate(Vector parvals, Vector types, Vector entities, Vector assocs) { if (parvals.size() == 0) @@ -2360,6 +2456,72 @@ public void saveModelData(PrintWriter out, Vector saved, Vector entities, Vector } } + + public Statement implementBehaviour(Vector types, Vector entities) + { System.out.println(">>> Activity = " + classifierBehaviour); + + if (classifierBehaviour != null) + { java.util.Map env = new java.util.HashMap(); + + Statement stat; + if (bx) + { stat = classifierBehaviour.statLC(env,false); } + else + { stat = classifierBehaviour.generateDesign(env,false); } + + System.out.println(">>> Activity = " + stat); + + Vector newparams = new Vector(); + newparams.addAll(parameters); + if (resultType != null) + { Attribute att = new Attribute("result",resultType,ModelElement.INTERNAL); + att.setElementType(elementType); + newparams.add(att); + } + Vector contexts = new Vector(); + newparams.addAll(ownedAttribute); + + Statement newstat = stat; + + if (activity != null) + { newstat = new SequenceStatement(); + ReturnStatement returnstat = null; + if (resultType != null && !("void".equals(resultType + ""))) + { Attribute att = new Attribute("result",resultType,ModelElement.INTERNAL); + att.setElementType(elementType); + CreationStatement cres = new CreationStatement(resultType + "", "result"); + cres.setInstanceType(resultType); + cres.setElementType(elementType); + ((SequenceStatement) newstat).addStatement(cres); + returnstat = new ReturnStatement(new BasicExpression(att)); + } + ((SequenceStatement) newstat).addStatement(stat); + Statement actstat = activity.generateDesign(env,false); + ((SequenceStatement) newstat).addStatement(actstat); + if (returnstat != null) + { ((SequenceStatement) newstat).addStatement(returnstat); } + } + else if (resultType != null && !("void".equals(resultType + ""))) + { newstat = new SequenceStatement(); + Attribute att = new Attribute("result",resultType,ModelElement.INTERNAL); + att.setElementType(elementType); + CreationStatement cres = new CreationStatement(resultType + "", "result"); + cres.setInstanceType(resultType); + cres.setElementType(elementType); + ((SequenceStatement) newstat).addStatement(cres); + ((SequenceStatement) newstat).addStatement(stat); + ReturnStatement returnstat = null; + returnstat = new ReturnStatement(new BasicExpression(att)); + ((SequenceStatement) newstat).addStatement(returnstat); + } + + + newstat.typeCheck(types,entities,contexts,newparams); + return newstat; + } + return new SequenceStatement(); + } + public void saveKM3(PrintWriter out, Vector saved) { // if (derived) { return; } @@ -2720,9 +2882,9 @@ public String jspQueryText(String op, String res = dec + "\n\r" + sets + "\n\r" + "\n\r" + - "" + op + " results\n\r" + + "" + op + " Results\n\r" + "\n\r" + - "

" + op + " results

\n\r" + + "

" + op + " Results

\n\r" + "<% Iterator " + bean + "s = " + bean + "." + op + "(); %>\n\r" + "\n\r" + @@ -2756,9 +2918,9 @@ public String getInputPage(String appname) // action.equals("remove")) // { method = "POST"; } String res = "\n\r" + - "" + op + " form\n\r" + + "" + op + " Form\n\r" + "\n\r" + - "

" + op + " form

\n\r" + + "

" + op + " Form

\n\r" + "\n\r"; Vector pars = getParameters(); for (int i = 0; i < pars.size(); i++) @@ -2897,6 +3059,260 @@ public BOp buildBUpdateOp(Entity ent, String opname, } */ + public String cg(CGSpec cgs, Vector types, Vector entities) + { String etext = this + ""; + Vector args = new Vector(); + args.add(getName()); + Vector eargs = new Vector(); + eargs.add(this); + String pars = ""; + + if (parameters == null) {} + else if (parameters.size() == 0) {} + else + { Attribute p = (Attribute) parameters.get(0); + Vector partail = new Vector(); + partail.addAll(parameters); + partail.remove(0); + pars = p.cgParameter(cgs,partail); + } + args.add(pars); + eargs.add(parameters); + + + + /* if (parameters == null) {} + else if (parameters.size() == 0) {} + else + { Attribute p = (Attribute) parameters.get(0); + Vector partail = new Vector(); + partail.addAll(parameters); + partail.remove(0); + pars = p.cgParameter(cgs,partail); + } + args.add(pars); */ + + if (resultType != null) + { args.add(resultType.cg(cgs)); + eargs.add(resultType); + } + else + { Type rt = new Type("void",null); + args.add(rt.cg(cgs)); + eargs.add(rt); + } + + /* + if (pre != null) + { args.add(pre.cg(cgs)); } + else + { BasicExpression pr = new BasicExpression(true); + args.add(pr.cg(cgs)); + } + + if (post != null) + { args.add(post.cg(cgs)); } + else + { BasicExpression pst = new BasicExpression(true); + args.add(pst.cg(cgs)); + } */ + + if (classifierBehaviour != null) + { Statement impl = implementBehaviour(types,entities); + args.add(impl.cg(cgs)); + eargs.add(impl); + } + else + { Statement nullstat = new SequenceStatement(); + args.add(nullstat.cg(cgs)); + eargs.add(nullstat); + } + // only one Use Case rule? + // maybe for static/cached + + CGRule r = cgs.matchedUsecaseRule(this,etext); + if (r != null) + { return r.applyRule(args,eargs,cgs); } + return etext; + } + + public String cgActivity(CGSpec cgs, Vector types, Vector entities) + { java.util.Map env = new java.util.HashMap(); + + if (classifierBehaviour != null) + { // Statement impl = implementBehaviour(types,entities); + Statement stat = classifierBehaviour.generateDesign(env,false); + System.out.println(">>> Use case implementation is: " + stat); + if (stat != null) + { return stat.cg(cgs); } + } + Statement nullstat = new SequenceStatement(); + return ""; + } + + public String getAndroidValueObject() + { return getValueObject("com.example.app"); } + + + public String getValueObject(String pge) + { String res = "package " + pge + ";\n\n"; + String nme = getName(); + res = res + "public class " + nme + "VO\n" + + "{ \n"; + + for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + String attnme = att.getName(); + String tname = att.getType().getJava(); + if (tname.equals("boolean")) + { tname = "String"; } + res = res + " private " + tname + " " + attnme + ";\n"; + } + + res = res + "\n" + + " public " + nme + "VO() {}\n\n"; + + if (parameters.size() > 0) + { res = res + " public " + nme + "VO("; + boolean previous = false; + + for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + String tname = att.getType().getJava(); + if (tname.equals("boolean")) + { tname = "String"; } + + String par = tname + " " + att.getName() + "x"; + if (previous) + { res = res + "," + par; } + else + { res = res + par; + previous = true; + } + } + res = res + ")\n { "; + + for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + String attnme = att.getName(); + res = res + " " + attnme + " = " + attnme + "x;\n"; + } + res = res + " }\n\n"; + } + + for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + String attnme = att.getName(); + String tname = att.getType().getJava(); + if (tname.equals("boolean")) + { tname = "String"; } + + res = res + " public " + tname + " get" + attnme + "()\n { " + + "return " + attnme + "; }\n\n"; + } + + for (int i = 0; i < parameters.size(); i++) + { Attribute att = (Attribute) parameters.get(i); + String attnme = att.getName(); + String tname = att.getType().getJava(); + if (tname.equals("boolean")) + { tname = "String"; } + + res = res + " public void set" + attnme + "(" + tname + " _x)\n { " + + attnme + " = _x; }\n\n"; + } + + return res + "}\n\n"; + } + + public String generateAndroidBean(Vector entities, + Vector types) + { String ename = getName(); + String res = "package com.example.app;\n\n" + + "import java.util.ArrayList;\n\n" + + "import java.util.List;\n\n" + + "import android.content.Context;\n\n" + + "public class " + ename + "Bean\n{ ModelFacade model = null;\n\n"; + + Attribute resultAttribute = getResultParameter(); + + Vector attributes = new Vector(); + attributes.addAll(parameters); + + for (int i = 0; i < attributes.size(); i++) + { Attribute att = (Attribute) attributes.get(i); + String attnme = att.getName(); + String tname = att.getType().getName(); + res = res + " private String " + attnme + " = \"\";\n"; + if (tname.equals("int") || tname.equals("long")) + { res = res + " private int i" + attnme + " = 0;\n"; } + else if (tname.equals("double")) + { res = res + " private double d" + attnme + " = 0;\n"; } + // booleans are treated as strings. + } + res = res + " private List errors = new ArrayList();\n\n" + + " public " + ename + "Bean(Context _c) { model = ModelFacade.getInstance(_c); }\n\n"; + for (int i = 0; i < attributes.size(); i++) + { Attribute att = (Attribute) attributes.get(i); + String attnme = att.getName(); + res = res + " public void set" + attnme + "(String " + attnme + "x)\n { " + + attnme + " = " + attnme + "x; }\n\n"; + } + + res = res + " public void resetData()\n { "; + for (int i = 0; i < attributes.size(); i++) + { Attribute att = (Attribute) attributes.get(i); + String attname = att.getName(); + res = res + attname + " = \"\";\n "; + } + res = res + "}\n\n"; + + res = res + " public boolean is" + ename + "error()\n" + + " { errors.clear(); \n"; + + String parstring = ""; + for (int k = 0; k < parameters.size(); k++) + { Attribute att = (Attribute) parameters.get(k); + String attnme = att.getName(); + Type atype = att.getType(); + String tname = atype.getName(); + String check = att.getBeanCheckCode(); + res = res + check; + + if (tname.equals("int") || tname.equals("long")) + { parstring = parstring + "i" + attnme; } + else if (tname.equals("double")) + { parstring = parstring + "d" + attnme; } + else + { parstring = parstring + attnme; } + if (k < parameters.size() - 1) + { parstring = parstring + ","; } + } + res = res + " return errors.size() > 0;\n }\n\n"; + + res = res + " public String errors() { return errors.toString(); }\n\n"; + + if (resultAttribute == null) + { res = res + " public void " + ename + "()\n" + " { "; + res = res + "model." + ename + "(" + parstring + ");" + " }\n\n"; + } + else + { Type t = resultAttribute.getType(); + String jType = t.getJava7(); + res = res + " public " + jType + " " + ename + "()\n" + " { "; + res = res + "return model." + ename + "(" + parstring + ");" + " }\n\n"; + } + return res + "}\n"; + } + + public void androidTabItem(PrintWriter out) + { String fullop = getName(); + String titleop = Named.capitalise(fullop); + out.println(" "); + } + } diff --git a/ValueMatching.java b/ValueMatching.java new file mode 100644 index 00000000..c402b3e5 --- /dev/null +++ b/ValueMatching.java @@ -0,0 +1,15 @@ +public class ValueMatching +{ Expression src; + Expression trg; + + public ValueMatching(Expression s, Expression t) + { src = s; + trg = t; + } + + public String toString() + { return src + " |--> " + trg; } + + public ValueMatching invert() + { return new ValueMatching(trg,src); } +} diff --git a/VectorUtil.java b/VectorUtil.java index cab8edd1..f2b60568 100644 --- a/VectorUtil.java +++ b/VectorUtil.java @@ -174,6 +174,18 @@ public static boolean vectorEqual(Vector v1, Vector v2) } + public static Vector removeByName(final Vector vs, final String s) + { Vector res = new Vector(); + for (int i = 0; i < vs.size(); i++) + { Object obj = vs.elementAt(i); + if ((obj + "").equals(s)) + { } + else + { res.add(obj); } + } + return res; + } + public static Vector removeAllEqualString(final String s, final Vector vs) { Vector res = new Vector(); for (int i = 0; i < vs.size(); i++)