From b600327d73e84be42d695de280d1c05d7bbca7cd Mon Sep 17 00:00:00 2001 From: Kevin Lano Date: Wed, 6 May 2020 15:48:04 +0100 Subject: [PATCH] Update of files Files changed since version1.9 first release in October 2019. Includes support for TL and CSTL languages (see the cgrules.pdf and mtsynth.pdf files). Provisional support for Android synthesis. --- AndroidAppGenerator.java | 564 +++ AppGenerator.java | 14 + Association.java | 11 +- AttEditDialog.java | 13 +- Attribute.java | 327 +- AttributeMatching.java | 1686 ++++++++- AuxMath.java | 668 ++++ BSystemTypes.java | 1120 +++++- BasicExpression.java | 283 +- BehaviouralFeature.java | 138 +- BinaryExpression.java | 1305 +++++-- Binding.java | 11 + CGCondition.java | 204 ++ CGRule.java | 675 ++++ CGSpec.java | 822 +++++ CSTL.java | 193 ++ CollectionTemplateExp.java | 347 ++ Compiler2.java | 6022 +++++++++++++++++++++++++++++++++ ConditionalExpression.java | 768 +++++ Constraint.java | 64 +- ConstraintGroup.java | 27 + ConstraintOrGroup.java | 6 + Domain.java | 4 +- DomainPattern.java | 14 +- Entity.java | 392 ++- EntityMatching.java | 1924 +++++++++-- EtlModule.java | 33 +- Expression.java | 94 +- IOSAppGenerator.java | 370 ++ Maplet.java | 4 + ModelElement.java | 67 +- ModelMatching.java | 928 ++++- ModelSpecification.java | 206 ++ ObjectSpecification.java | 117 +- ObjectTemplateExp.java | 116 +- OperationDescription.java | 869 ++++- OutPatternElement.java | 13 + Pattern.java | 70 +- PrimitiveDomain.java | 6 +- PropertyTemplateItem.java | 60 +- RectData.java | 7 + Relation.java | 145 +- RelationDomain.java | 20 +- RelationalTransformation.java | 69 +- SetExpression.java | 168 +- Statement.java | 562 ++- SystemTypes.java | 10 +- TemplateExp.java | 5 +- Thesarus.java | 18 +- TransformationRule.java | 98 +- Type.java | 404 ++- TypeMatching.java | 61 + UCDArea.java | 1181 ++++++- UmlTool.java | 93 +- UnaryExpression.java | 101 +- UseCase.java | 434 ++- ValueMatching.java | 15 + VectorUtil.java | 12 + 58 files changed, 22683 insertions(+), 1275 deletions(-) create mode 100644 AndroidAppGenerator.java create mode 100644 AppGenerator.java create mode 100644 AuxMath.java create mode 100644 CGCondition.java create mode 100644 CGRule.java create mode 100644 CGSpec.java create mode 100644 CSTL.java create mode 100644 CollectionTemplateExp.java create mode 100644 Compiler2.java create mode 100644 ConditionalExpression.java create mode 100644 IOSAppGenerator.java create mode 100644 ModelSpecification.java create mode 100644 TypeMatching.java create mode 100644 ValueMatching.java 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++)