diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PULL-first/Hour.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PULL-first/Hour.java index 063d06b..a7acf75 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PULL-first/Hour.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PULL-first/Hour.java @@ -9,23 +9,20 @@ @Path("/hour") @Component public class Hour { - private double value = 0.0; + private int value = 0; @Produces(MediaType.APPLICATION_JSON) @GET - public double getValue() { + public int getValue() { return value; } @POST - public void updateFromMin(@FormParam("min") double min) { - double temp_if2; + public void updateFromMin(@FormParam("min") int min) { + int temp_if0; if ((min==0)) { - temp_if2 = ((this.value+1)%24); + temp_if0 = ((this.value+1)%24); } else { - temp_if2 = this.value; + temp_if0 = this.value; } - this.value = temp_if2; - } - public Hour(double hour) { - this.hour = hour; + this.value = temp_if0; } } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PULL-first/Hour_ang.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PULL-first/Hour_ang.java index d237f76..9c14018 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PULL-first/Hour_ang.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PULL-first/Hour_ang.java @@ -13,7 +13,7 @@ @Produces(MediaType.APPLICATION_JSON) @GET public double getValue() { - double hour = client.target("http://localhost:8080").path("/hour").request().get(double.class); + int hour = client.target("http://localhost:8080").path("/hour").request().get(int.class); return ((hour/6)*Math.PI); } } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PULL-first/Min.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PULL-first/Min.java index a4589a3..db4cea5 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PULL-first/Min.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PULL-first/Min.java @@ -9,20 +9,17 @@ @Path("/min") @Component public class Min { - private double value = 0.0; + private int value = 0; private Client client = ClientBuilder.newClient(); @Produces(MediaType.APPLICATION_JSON) @GET - public double getValue() { + public int getValue() { return value; } - public Min(double min) { - this.min = min; - } @POST public void tick() throws JsonProcessingException { Form form = new Form(); - form.param("min", Double.toString(this.value)); + form.param("min", Integer.toString(this.value)); Entity
entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED); String result = client.target("http://localhost:8080").path("/hour").request().post(entity, String.class); this.value = ((this.value+1)%60); diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PULL-first/Min_ang.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PULL-first/Min_ang.java index 172cca8..96ae12b 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PULL-first/Min_ang.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PULL-first/Min_ang.java @@ -13,7 +13,7 @@ @Produces(MediaType.APPLICATION_JSON) @GET public double getValue() { - double min = client.target("http://localhost:8080").path("/min").request().get(double.class); + int min = client.target("http://localhost:8080").path("/min").request().get(int.class); return ((min/30)*Math.PI); } } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PUSH-first/Hour.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PUSH-first/Hour.java index 7733bfe..12f10e1 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PUSH-first/Hour.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PUSH-first/Hour.java @@ -18,19 +18,16 @@ } @POST public void updateFromMin(@FormParam("min") double min) throws JsonProcessingException { - double temp_if3; + double temp_if1; if ((min==0)) { - temp_if3 = ((this.value+1)%24); + temp_if1 = ((this.value+1)%24); } else { - temp_if3 = this.value; + temp_if1 = this.value; } - this.value = temp_if3; + this.value = temp_if1; Form form = new Form(); form.param("hour", Double.toString(this.value)); Entity entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED); String result = client.target("http://localhost:8080").path("/hour_ang").request().put(entity, String.class); } - public Hour(double hour) { - this.hour = hour; - } } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PUSH-first/Hour_ang.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PUSH-first/Hour_ang.java index 45c2864..5412a9a 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PUSH-first/Hour_ang.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PUSH-first/Hour_ang.java @@ -19,7 +19,4 @@ public void updateFromHour(@FormParam("hour") double hour) { this.value = ((hour/6)*Math.PI); } - public Hour_ang(double hour_ang) { - this.hour_ang = hour_ang; - } } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PUSH-first/Min.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PUSH-first/Min.java index b72f252..f068cb6 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PUSH-first/Min.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PUSH-first/Min.java @@ -16,9 +16,6 @@ public double getValue() { return value; } - public Min(double min) { - this.min = min; - } @POST public void tick() throws JsonProcessingException { Form form = new Form(); diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PUSH-first/Min_ang.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PUSH-first/Min_ang.java index be7e6fb..b467b97 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PUSH-first/Min_ang.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/Clock/PUSH-first/Min_ang.java @@ -19,7 +19,4 @@ public void updateFromMin(@FormParam("min") double min) { this.value = ((min/30)*Math.PI); } - public Min_ang(double min_ang) { - this.min_ang = min_ang; - } } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/GroupChat/Account.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/GroupChat/Account.java index 159f403..5f97d07 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/GroupChat/Account.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/GroupChat/Account.java @@ -3,14 +3,14 @@ public class Account { private Map notifications; public Map getValue() { - Map temp_nil1 = new HashMap<>(); - temp_nil1.put("notifications",this.getNotifications()); - return temp_nil1; + Map temp_nil3 = new HashMap<>(); + temp_nil3.put("notifications",this.getNotifications()); + return temp_nil3; } public Map getNotifications() { return notifications; } - public void updateNotificationsFromMessages(String self, String gid, int mno, List messages, String members) { + public void updateNotificationsFromMessages(String self, String gid, int mno, List messages, String member) { this.notifications.put(gid,true); } public void hasRead(String aid, String gid) { diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/GroupChat/Accounts.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/GroupChat/Accounts.java index 6183f07..35ef30a 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/GroupChat/Accounts.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/GroupChat/Accounts.java @@ -20,8 +20,8 @@ } @Path("accounts/{v1}/notifications") @POST - public void updateNotificationsFromMessages(@PathParam("v1") String v1, @FormParam("gid") String gid, @FormParam("mno") int mno, @FormParam("messages") List messages, @FormParam("members") String members) { - getAccount(v1).updateNotificationsFromMessages(m.get(mno), gid, mno, messages, members); + public void updateNotificationsFromMessages(@PathParam("v1") String v1, @FormParam("gid") String gid, @FormParam("mno") int mno, @FormParam("messages") List messages, @FormParam("member") String member) { + getAccount(v1).updateNotificationsFromMessages(v1, gid, mno, messages, member); } @Path("/{v1}") @Produces(MediaType.APPLICATION_JSON) @@ -29,11 +29,11 @@ public Map getAccountValue(@PathParam("v1") String v1) { return getAccount(v1).getValue(); } - @Path("/{v1}/notifications") + @Path("/{aid}/notifications") @Produces(MediaType.APPLICATION_JSON) @GET - public Map getNotificationsValue(@PathParam("v1") String v1) { - return getAccount(v1).getNotifications(); + public Map getNotificationsValue(@PathParam("aid") String aid) { + return getAccount(aid).getNotifications(); } @Path("/{aid}/notifications") @DELETE diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/GroupChat/Group.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/GroupChat/Group.java index 08338b0..3579e08 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/GroupChat/Group.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/GroupChat/Group.java @@ -3,22 +3,22 @@ public class Group { private List members; - private Client client = ClientBuilder.newClient(); private List messages; + private Client client = ClientBuilder.newClient(); public Map getValue() { - Map temp_nil0 = new HashMap<>(); - temp_nil0.put("messages",this.getMessages()); - temp_nil0.put("members",this.getMembers()); - return temp_nil0; + Map temp_nil2 = new HashMap<>(); + temp_nil2.put("messages",this.getMessages()); + temp_nil2.put("members",this.getMembers()); + return temp_nil2; } - public List getMessages() { - return this.messages; + public String getMember(int mno) { + return this.members.get(mno); } public List getMembers() { return this.members; } - public String getMember(int mno) { - return this.members.get(mno); + public List getMessages() { + return this.messages; } public void postMessage(String gid, String message) throws JsonProcessingException { for (int mno = 0; mno < members.size(); mno++) { diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/GroupChat/Groups.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/GroupChat/Groups.java index cc91714..e00259d 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/GroupChat/Groups.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/GroupChat/Groups.java @@ -18,11 +18,11 @@ public Group getGroup(String gid) { return this.value.get(gid); } - @Path("/{gid}") + @Path("/{gid}/members/{mno}") @Produces(MediaType.APPLICATION_JSON) @GET - public Map getGroupValue(@PathParam("gid") String gid) { - return getGroup(gid).getValue(); + public String getMemberValue(@PathParam("gid") String gid, @PathParam("mno") int mno) { + return getGroup(gid).getMember(mno); } @Path("/{gid}/messages") @Produces(MediaType.APPLICATION_JSON) @@ -30,11 +30,11 @@ public List getMessagesValue(@PathParam("gid") String gid) { return getGroup(gid).getMessages(); } - @Path("/{gid}/members/{mno}") + @Path("/{gid}") @Produces(MediaType.APPLICATION_JSON) @GET - public String getMemberValue(@PathParam("gid") String gid, @PathParam("mno") int mno) { - return getGroup(gid).getMember(mno); + public Map getGroupValue(@PathParam("gid") String gid) { + return getGroup(gid).getValue(); } @Path("/{gid}/members") @Produces(MediaType.APPLICATION_JSON) @@ -42,15 +42,15 @@ public List getMembersValue(@PathParam("gid") String gid) { return getGroup(gid).getMembers(); } - @POST - public void createGroup(@FormParam("gid") String gid) { - this.value.put(gid,new Group(new ArrayList<>(), new ArrayList<>())); - } @Path("/{gid}/messages") @POST public void postMessage(@PathParam("gid") String gid, @FormParam("message") String message) throws JsonProcessingException { getGroup(gid).postMessage(gid, message); } + @POST + public void createGroup(@FormParam("gid") String gid) { + this.value.put(gid,new Group(new ArrayList<>(), new ArrayList<>())); + } @Path("/{gid}/members") @POST public void addGroupMember(@PathParam("gid") String gid, @FormParam("aid") String aid) { diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Account.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Account.java index ff5dda3..f7594e2 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Account.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Account.java @@ -1,28 +1,27 @@ import java.util.*; public class Account { - private String name; private int point; + private String name; public Map getValue() { - Map temp_nil9 = new HashMap<>(); - temp_nil9.put("point",this.getPoint()); - temp_nil9.put("name",this.getName()); - return temp_nil9; - } - public String getName() { - return this.name; + Map temp_nil4 = new HashMap<>(); + temp_nil4.put("name",this.getName()); + temp_nil4.put("point",this.getPoint()); + return temp_nil4; } public int getPoint() { return point; } + public String getName() { + return this.name; + } public void updatePointFromBattle(String self, String rid, int mno, boolean battle, String id) { - int temp_if0; - if (hasWon) { - temp_if0 = (this.point+1); + int temp_if1; + if (battle) { + temp_if1 = (this.point+1); } else { - temp_if0 = this.point; - } - this.point = temp_if0; + temp_if1 = this.point; + }this.point = temp_if1; } public void changeName(String aid, String name) { this.name = name; diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Accounts.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Accounts.java index 0e9528b..9ec4085 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Accounts.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Accounts.java @@ -41,13 +41,13 @@ public String getNameValue(@PathParam("mid") String mid) { return getAccount(mid).getName(); } - @POST - public void signUp(@FormParam("name") String name, @FormParam("aid") String aid) { - this.value.put(aid,new Account(name, 0)); - } @Path("/{aid}/name") @PUT public void changeName(@PathParam("aid") String aid, @FormParam("name") String name) { getAccount(aid).changeName(aid, name); } + @POST + public void signUp(@FormParam("name") String name, @FormParam("aid") String aid) { + this.value.put(aid,new Account(name, 0)); + } } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Member.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Member.java index f721703..e566317 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Member.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Member.java @@ -2,21 +2,21 @@ import javax.ws.rs.client.*; public class Member { - private Client client = ClientBuilder.newClient(); private String id; + private Client client = ClientBuilder.newClient(); public Map getValue() { - Map temp_nil10 = new HashMap<>(); - temp_nil10.put("name",this.getName()); - temp_nil10.put("id",this.getId()); - return temp_nil10; + Map temp_nil5 = new HashMap<>(); + temp_nil5.put("name",this.getName()); + temp_nil5.put("id",this.getId()); + return temp_nil5; + } + public String getId() { + return this.id; } public String getName() { String name = client.target("http://localhost:8080").path("/accounts."+id+".name").request().get(String.class); return name; } - public String getId() { - return this.id; - } public Member(String id) { this.id = id; } diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Room.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Room.java index 581174c..55dce69 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Room.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Room.java @@ -6,10 +6,10 @@ private boolean battle; private Client client = ClientBuilder.newClient(); public Map getValue() { - Map temp_nil8 = new HashMap<>(); - temp_nil8.put("members",this.members.getValue()); - temp_nil8.put("battle",this.getBattle()); - return temp_nil8; + Map temp_nil3 = new HashMap<>(); + temp_nil3.put("members",this.members.getValue()); + temp_nil3.put("battle",this.getBattle()); + return temp_nil3; } public Members getMembers() { return this.members; diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Rooms.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Rooms.java index 8e0cde3..c0b7951 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Rooms.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/OnlineBattleGame2/Rooms.java @@ -30,12 +30,6 @@ public Map getMemberValue(@PathParam("rid") String rid, @PathParam("mno") int mno) { return getRoom(rid).getMembers().getMember(mno).getValue(); } - @Path("/{rid}/members/{mno}/id") - @Produces(MediaType.APPLICATION_JSON) - @GET - public String getIdValue(@PathParam("rid") String rid, @PathParam("mno") int mno) { - return getRoom(rid).getMembers().getMember(mno).getId(); - } @Path("/{rid}") @Produces(MediaType.APPLICATION_JSON) @GET @@ -48,6 +42,12 @@ public List getMembersValue(@PathParam("rid") String rid) { return getRoom(rid).getMembers().getValue(); } + @Path("/{rid}/members/{mno}/id") + @Produces(MediaType.APPLICATION_JSON) + @GET + public String getIdValue(@PathParam("rid") String rid, @PathParam("mno") int mno) { + return getRoom(rid).getMembers().getMember(mno).getId(); + } @Path("/{rid}/battle") @Produces(MediaType.APPLICATION_JSON) @GET diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PULL-first/History.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PULL-first/History.java index 2038cd4..92776d5 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PULL-first/History.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PULL-first/History.java @@ -9,17 +9,14 @@ @Path("/history") @Component public class History { - private List value = new ArrayList<>(); + private List value = new ArrayList<>(); @Produces(MediaType.APPLICATION_JSON) @GET - public List getValue() { + public List getValue() { return value; } @POST - public void updateFromPayment(@FormParam("payment") double payment) { + public void updateFromPayment(@FormParam("payment") int payment) { this.value.add(0, payment); } - public History(List history) { - this.history = history; - } } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PULL-first/Payment.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PULL-first/Payment.java index 95332ef..a694ab6 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PULL-first/Payment.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PULL-first/Payment.java @@ -9,20 +9,17 @@ @Path("/payment") @Component public class Payment { - private double value = 0.0; + private int value = 0; private Client client = ClientBuilder.newClient(); @Produces(MediaType.APPLICATION_JSON) @GET - public double getValue() { + public int getValue() { return value; } - public Payment(double payment) { - this.payment = payment; - } @PUT - public void purchase(@FormParam("x") double x) throws JsonProcessingException { + public void purchase(@FormParam("x") int x) throws JsonProcessingException { Form form = new Form(); - form.param("payment", Double.toString(this.value)); + form.param("payment", Integer.toString(this.value)); Entity entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED); String result = client.target("http://localhost:8080").path("/history").request().post(entity, String.class); this.value = x; diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PULL-first/Points.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PULL-first/Points.java index c557cf6..f7ac799 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PULL-first/Points.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PULL-first/Points.java @@ -13,7 +13,7 @@ @Produces(MediaType.APPLICATION_JSON) @GET public int getValue() { - double payment = client.target("http://localhost:8080").path("/payment").request().get(double.class); + int payment = client.target("http://localhost:8080").path("/payment").request().get(int.class); return (int)Math.floor((payment*0.05)); } } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PULL-first/Total.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PULL-first/Total.java index 69d4735..87b8845 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PULL-first/Total.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PULL-first/Total.java @@ -13,7 +13,7 @@ @Produces(MediaType.APPLICATION_JSON) @GET public int getValue() { - List history = client.target("http://localhost:8080").path("/history").request().get(ArrayList.class); + List history = client.target("http://localhost:8080").path("/history").request().get(ArrayList.class); Integer temp_sum1 = 0; for (Integer x: history) { temp_sum1 += x; diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PUSH-first/History.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PUSH-first/History.java index 2a571d3..e6c5c7f 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PUSH-first/History.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PUSH-first/History.java @@ -19,7 +19,6 @@ @POST public void updateFromPayment(@FormParam("payment") double payment) throws JsonProcessingException { this.value.add(0, payment); - Form form = new Form(); for (Double i: this.value) { form.param("history", i.toString()); @@ -27,7 +26,4 @@ Entity entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED); String result = client.target("http://localhost:8080").path("/total").request().put(entity, String.class); } - public History(List history) { - this.history = history; - } } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PUSH-first/Payment.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PUSH-first/Payment.java index 18e64ef..5d65395 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PUSH-first/Payment.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PUSH-first/Payment.java @@ -16,9 +16,6 @@ public double getValue() { return value; } - public Payment(double payment) { - this.payment = payment; - } @PUT public void purchase(@FormParam("x") double x) throws JsonProcessingException { Form form = new Form(); diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PUSH-first/Points.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PUSH-first/Points.java index 7dc8d20..7071bf0 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PUSH-first/Points.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PUSH-first/Points.java @@ -19,7 +19,4 @@ public void updateFromPayment(@FormParam("payment") double payment) { this.value = (int)Math.floor((payment*0.05)); } - public Points(int points) { - this.points = points; - } } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PUSH-first/Total.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PUSH-first/Total.java index e91f4e7..0fdd957 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PUSH-first/Total.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/POS/PUSH-first/Total.java @@ -23,7 +23,4 @@ } this.value = temp_sum1; } - public Total(int total) { - this.total = total; - } } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/VotingSystem/Accounts.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/VotingSystem/Accounts.java index 90e5808..ab6b793 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/VotingSystem/Accounts.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/VotingSystem/Accounts.java @@ -18,6 +18,12 @@ public Account getAccount(String aid) { return this.value.get(aid); } + @Path("/{aid}/vote") + @Produces(MediaType.APPLICATION_JSON) + @GET + public String getVoteValue(@PathParam("aid") String aid) { + return getAccount(aid).getVote(); + } @Path("/{aid}") @Produces(MediaType.APPLICATION_JSON) @GET @@ -25,18 +31,12 @@ return getAccount(aid).getValue(); } @Path("/{aid}/vote") - @Produces(MediaType.APPLICATION_JSON) - @GET - public String getVoteValue(@PathParam("aid") String aid) { - return getAccount(aid).getVote(); + @PUT + public void cast(@PathParam("aid") String aid, @FormParam("v") String v) { + getAccount(aid).cast(aid, v); } @POST public void signUp(@FormParam("name") String name, @FormParam("aid") String aid) { this.value.put(aid,new Account(null)); } - @Path("/{aid}/vote") - @PUT - public void cast(@PathParam("aid") String aid, @FormParam("v") String v) { - getAccount(aid).cast(aid, v); - } } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/VotingSystem/Counts.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/VotingSystem/Counts.java index f841a6f..9baed06 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/VotingSystem/Counts.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/VotingSystem/Counts.java @@ -24,7 +24,4 @@ } return v0; } - public Counts(Map counts) { - this.counts = counts; - } } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PULL-first/Highest.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PULL-first/Highest.java index 71afbf6..0b95991 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PULL-first/Highest.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PULL-first/Highest.java @@ -17,16 +17,13 @@ } @POST public void updateFromTemp_f(@FormParam("temp_f") double temp_f) { - double temp_if4; + double temp_if2; if ((temp_f>=this.value)) { - temp_if4 = temp_f; + temp_if2 = temp_f; } else { - temp_if4 = this.value; + temp_if2 = this.value; } - this.value = temp_if4; - } - public Highest(double highest) { - this.highest = highest; + this.value = temp_if2; } @PUT public void reset(@FormParam("v") double v) { diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PULL-first/Temp_f.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PULL-first/Temp_f.java index 6cd8101..a23f614 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PULL-first/Temp_f.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PULL-first/Temp_f.java @@ -16,9 +16,6 @@ public double getValue() { return value; } - public Temp_f(double temp_f) { - this.temp_f = temp_f; - } @PUT public void observe(@FormParam("x") double x) throws JsonProcessingException { Form form = new Form(); diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PUSH-first/Highest.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PUSH-first/Highest.java index 89e309a..7196436 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PUSH-first/Highest.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PUSH-first/Highest.java @@ -25,9 +25,6 @@ } this.value = temp_if3; } - public Highest(double highest) { - this.highest = highest; - } @PUT public void reset(@FormParam("v") double v) { this.value = v; diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PUSH-first/Temp_c.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PUSH-first/Temp_c.java index b875714..ee3d10a 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PUSH-first/Temp_c.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PUSH-first/Temp_c.java @@ -19,7 +19,4 @@ public void updateFromTemp_f(@FormParam("temp_f") double temp_f) { this.value = ((temp_f-32)/1.8); } - public Temp_c(double temp_c) { - this.temp_c = temp_c; - } } \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PUSH-first/Temp_f.java b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PUSH-first/Temp_f.java index e9c4b93..a589b35 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PUSH-first/Temp_f.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/JAX-RS/WeatherObservationSystem/PUSH-first/Temp_f.java @@ -16,9 +16,6 @@ public double getValue() { return value; } - public Temp_f(double temp_f) { - this.temp_f = temp_f; - } @PUT public void observe(@FormParam("x") double x) throws JsonProcessingException { Form form = new Form(); diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/Companies.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/Companies.java new file mode 100644 index 0000000..148543f --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/Companies.java @@ -0,0 +1,14 @@ +import java.util.*; + +public class Companies { + private Map value = new HashMap<>(); + public Map getValue() { + return new HashMap<>(value); + } + public Company getCompany(String cid) { + return this.value.get(cid); + } + public void addCampany(String address, String cid) { + this.value.put(cid,new Company(address)); + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/Company.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/Company.java new file mode 100644 index 0000000..fd0eaba --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/Company.java @@ -0,0 +1,19 @@ +import java.util.*; + +public class Company { + private String address; + public Map getValue() { + Map temp_nil6 = new HashMap<>(); + temp_nil6.put("address",this.getAddress()); + return temp_nil6; + } + public String getAddress() { + return this.address; + } + public void setAddress(String cid, String add) { + this.address = add; + } + public Company(String address) { + this.address = address; + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/Customer.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/Customer.java new file mode 100644 index 0000000..4c19192 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/Customer.java @@ -0,0 +1,28 @@ +import java.util.*; + +public class Customer { + private String organization; + private Company company; + private Companies companies; + public Map getValue() { + Map temp_nil7 = new HashMap<>(); + temp_nil7.put("address",this.getAddress()); + temp_nil7.put("organization",this.getOrganization()); + return temp_nil7; + } + public String getOrganization() { + return this.organization; + } + public String getAddress() { + return this.company.getAddress(); + } + public void setOrganization(String uid, String cid) { + this.organization = cid; + this.company = this.companies.getCompany(this.organization); + } + public Customer(String organization, Companies companies) { + this.organization = organization; + this.companies = companies; + this.company = this.companies.getCompany(this.organization); + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/CustomerManagement.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/CustomerManagement.java new file mode 100644 index 0000000..a919176 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/CustomerManagement.java @@ -0,0 +1,43 @@ +import java.util.*; + +public class CustomerManagement { + private Companies companies; + private Customers customers; + public CustomerManagement() { + companies = new Companies(); + customers = new Customers(companies); + } + public Map getCompanies() { + return this.companies.getValue(); + } + public void addCampany(String address, String cid) { + this.companies.addCampany(address, cid); + } + public String getAddress(String cid) { + return this.companies.getCompany(cid).getAddress(); + } + public void setAddress(String cid, String add) { + this.companies.getCompany(cid).setAddress(cid, add); + } + public String getOrganization(String uid) { + return this.customers.getCustomer(uid).getOrganization(); + } + public void setOrganization(String uid, String cid) { + this.customers.getCustomer(uid).setOrganization(uid, cid); + } + public String getAddress(String uid) { + return this.customers.getCustomer(uid).getAddress(); + } + public Map getCompany(String cid) { + return this.companies.getCompany(cid).getValue(); + } + public Map getCustomers() { + return this.customers.getValue(); + } + public void addCustomer(String org, String uid) { + this.customers.addCustomer(org, uid); + } + public Map getCustomer(String uid) { + return this.customers.getCustomer(uid).getValue(); + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/Customers.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/Customers.java new file mode 100644 index 0000000..04725d7 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/Customers.java @@ -0,0 +1,18 @@ +import java.util.*; + +public class Customers { + private Map value = new HashMap<>(); + private Companies companies; + public Map getValue() { + return new HashMap<>(value); + } + public Customer getCustomer(String uid) { + return this.value.get(uid); + } + public void addCustomer(String org, String uid) { + this.value.put(uid,new Customer(org, companies)); + } + public Customers(Companies companies) { + this.companies = companies; + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/PULL-first/Companies.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/PULL-first/Companies.java deleted file mode 100644 index 148543f..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/PULL-first/Companies.java +++ /dev/null @@ -1,14 +0,0 @@ -import java.util.*; - -public class Companies { - private Map value = new HashMap<>(); - public Map getValue() { - return new HashMap<>(value); - } - public Company getCompany(String cid) { - return this.value.get(cid); - } - public void addCampany(String address, String cid) { - this.value.put(cid,new Company(address)); - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/PULL-first/Company.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/PULL-first/Company.java deleted file mode 100644 index fd0eaba..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/PULL-first/Company.java +++ /dev/null @@ -1,19 +0,0 @@ -import java.util.*; - -public class Company { - private String address; - public Map getValue() { - Map temp_nil6 = new HashMap<>(); - temp_nil6.put("address",this.getAddress()); - return temp_nil6; - } - public String getAddress() { - return this.address; - } - public void setAddress(String cid, String add) { - this.address = add; - } - public Company(String address) { - this.address = address; - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/PULL-first/Customer.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/PULL-first/Customer.java deleted file mode 100644 index 4c19192..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/PULL-first/Customer.java +++ /dev/null @@ -1,28 +0,0 @@ -import java.util.*; - -public class Customer { - private String organization; - private Company company; - private Companies companies; - public Map getValue() { - Map temp_nil7 = new HashMap<>(); - temp_nil7.put("address",this.getAddress()); - temp_nil7.put("organization",this.getOrganization()); - return temp_nil7; - } - public String getOrganization() { - return this.organization; - } - public String getAddress() { - return this.company.getAddress(); - } - public void setOrganization(String uid, String cid) { - this.organization = cid; - this.company = this.companies.getCompany(this.organization); - } - public Customer(String organization, Companies companies) { - this.organization = organization; - this.companies = companies; - this.company = this.companies.getCompany(this.organization); - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/PULL-first/CustomerManagement.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/PULL-first/CustomerManagement.java deleted file mode 100644 index a919176..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/PULL-first/CustomerManagement.java +++ /dev/null @@ -1,43 +0,0 @@ -import java.util.*; - -public class CustomerManagement { - private Companies companies; - private Customers customers; - public CustomerManagement() { - companies = new Companies(); - customers = new Customers(companies); - } - public Map getCompanies() { - return this.companies.getValue(); - } - public void addCampany(String address, String cid) { - this.companies.addCampany(address, cid); - } - public String getAddress(String cid) { - return this.companies.getCompany(cid).getAddress(); - } - public void setAddress(String cid, String add) { - this.companies.getCompany(cid).setAddress(cid, add); - } - public String getOrganization(String uid) { - return this.customers.getCustomer(uid).getOrganization(); - } - public void setOrganization(String uid, String cid) { - this.customers.getCustomer(uid).setOrganization(uid, cid); - } - public String getAddress(String uid) { - return this.customers.getCustomer(uid).getAddress(); - } - public Map getCompany(String cid) { - return this.companies.getCompany(cid).getValue(); - } - public Map getCustomers() { - return this.customers.getValue(); - } - public void addCustomer(String org, String uid) { - this.customers.addCustomer(org, uid); - } - public Map getCustomer(String uid) { - return this.customers.getCustomer(uid).getValue(); - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/PULL-first/Customers.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/PULL-first/Customers.java deleted file mode 100644 index 04725d7..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/CustomerManagement/PULL-first/Customers.java +++ /dev/null @@ -1,18 +0,0 @@ -import java.util.*; - -public class Customers { - private Map value = new HashMap<>(); - private Companies companies; - public Map getValue() { - return new HashMap<>(value); - } - public Customer getCustomer(String uid) { - return this.value.get(uid); - } - public void addCustomer(String org, String uid) { - this.value.put(uid,new Customer(org, companies)); - } - public Customers(Companies companies) { - this.companies = companies; - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/Account.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/Account.java new file mode 100644 index 0000000..10f53f1 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/Account.java @@ -0,0 +1,22 @@ +import java.util.*; + +public class Account { + private Map notifications; + public Map getValue() { + Map temp_nil17 = new HashMap<>(); + temp_nil17.put("notifications",this.getNotifications()); + return temp_nil17; + } + public Map getNotifications() { + return new HashMap<>(notifications); + } + public void updateNotificationsFromMessages(String self, String gid, int mno, List messages, String member) { + this.notifications.put(gid,true); + } + public void hasRead(String aid, String gid) { + this.notifications.remove(gid); + } + public Account(Map notifications) { + this.notifications = notifications; + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/Accounts.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/Accounts.java new file mode 100644 index 0000000..2e7c4e3 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/Accounts.java @@ -0,0 +1,14 @@ +import java.util.*; + +public class Accounts { + private Map value = new HashMap<>(); + public Map getValue() { + return new HashMap<>(value); + } + public Account getAccount(String v1) { + return this.value.get(v1); + } + public void signUp(String aid) { + this.value.put(aid,new Account(new HashMap<>())); + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/Group.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/Group.java new file mode 100644 index 0000000..faa7d19 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/Group.java @@ -0,0 +1,39 @@ +import java.util.*; + +public class Group { + private List messages; + private Account account; + private Accounts accounts; + private List members; + public Map getValue() { + Map temp_nil16 = new HashMap<>(); + temp_nil16.put("members",this.getMembers()); + temp_nil16.put("messages",this.getMessages()); + return temp_nil16; + } + public List getMessages() { + return this.messages; + } + public List getMembers() { + return this.members; + } + public String getMember(int mno) { + return this.members.get(mno); + } + public void postMessage(String gid, String message) { + this.messages.add(message); + for (int mno = 0; mno < this.members.size(); mno++) { + String member = getMember(mno); + this.account = accounts.getAccount(member); + this.account.updateNotificationsFromMessages(member, gid, mno, messages, member); + } + } + public void addGroupMember(String gid, String aid) { + this.members.add(aid); + } + public Group(List messages, Accounts accounts, List members) { + this.messages = messages; + this.accounts = accounts; + this.members = members; + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/GroupChat.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/GroupChat.java new file mode 100644 index 0000000..6ee5abf --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/GroupChat.java @@ -0,0 +1,49 @@ +import java.util.*; + +public class GroupChat { + private Accounts accounts; + private Groups groups; + public GroupChat() { + accounts = new Accounts(); + groups = new Groups(accounts); + } + public Map getGroup(String gid) { + return this.groups.getGroup(gid).getValue(); + } + public Map getAccount(String v1) { + return this.accounts.getAccount(v1).getValue(); + } + public List getMessages(String gid) { + return this.groups.getGroup(gid).getMessages(); + } + public void postMessage(String gid, String message) { + this.groups.getGroup(gid).postMessage(gid, message); + } + public List getMembers(String gid) { + return this.groups.getGroup(gid).getMembers(); + } + public void addGroupMember(String gid, String aid) { + this.groups.getGroup(gid).addGroupMember(gid, aid); + } + public Map getNotifications(String v1) { + return this.accounts.getAccount(v1).getNotifications(); + } + public void hasRead(String aid, String gid) { + this.accounts.getAccount(aid).hasRead(aid, gid); + } + public String getMember(String gid, int mno) { + return this.groups.getGroup(gid).getMember(mno); + } + public Map getAccounts() { + return this.accounts.getValue(); + } + public void signUp(String aid) { + this.accounts.signUp(aid); + } + public Map getGroups() { + return this.groups.getValue(); + } + public void createGroup(String gid) { + this.groups.createGroup(gid); + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/Groups.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/Groups.java new file mode 100644 index 0000000..ada656a --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/Groups.java @@ -0,0 +1,18 @@ +import java.util.*; + +public class Groups { + private Map value = new HashMap<>(); + private Accounts accounts; + public Map getValue() { + return new HashMap<>(value); + } + public Group getGroup(String gid) { + return this.value.get(gid); + } + public void createGroup(String gid) { + this.value.put(gid,new Group(new ArrayList<>(), accounts, new ArrayList<>())); + } + public Groups(Accounts accounts) { + this.accounts = accounts; + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PULL-first/Account.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PULL-first/Account.java deleted file mode 100644 index 6aa36f4..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PULL-first/Account.java +++ /dev/null @@ -1,22 +0,0 @@ -import java.util.*; - -public class Account { - private Map notifications; - public Map getValue() { - Map temp_nil5 = new HashMap<>(); - temp_nil5.put("notifications",this.getNotifications()); - return temp_nil5; - } - public Map getNotifications() { - return new HashMap<>(notifications); - } - public void updateNotificationsFromMessages(String gid, int mno, List messages, String members) { - this.notifications.put(gid,true); - } - public void hasRead(String aid, String gid) { - this.notifications.remove(gid); - } - public Account(Map notifications) { - this.notifications = notifications; - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PULL-first/Accounts.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PULL-first/Accounts.java deleted file mode 100644 index 2e7c4e3..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PULL-first/Accounts.java +++ /dev/null @@ -1,14 +0,0 @@ -import java.util.*; - -public class Accounts { - private Map value = new HashMap<>(); - public Map getValue() { - return new HashMap<>(value); - } - public Account getAccount(String v1) { - return this.value.get(v1); - } - public void signUp(String aid) { - this.value.put(aid,new Account(new HashMap<>())); - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PULL-first/Group.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PULL-first/Group.java deleted file mode 100644 index 7a9159a..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PULL-first/Group.java +++ /dev/null @@ -1,39 +0,0 @@ -import java.util.*; - -public class Group { - private List members; - private List messages; - private Account account; - private Accounts accounts; - public Map getValue() { - Map temp_nil4 = new HashMap<>(); - temp_nil4.put("messages",this.getMessages()); - temp_nil4.put("members",this.getMembers()); - return temp_nil4; - } - public List getMembers() { - return this.members; - } - public List getMessages() { - return this.messages; - } - public String getMember(int mno) { - return this.members.get(mno); - } - public void postMessage(String gid, String message) { - this.messages.add(message); - for (int mno = 0; mno < this.members.size(); mno++) { - String member = getMember(mno); - this.account = accounts.getAccount(member); - this.account.updateNotificationsFromMessages(gid, mno, messages, member); - } - } - public void addGroupMember(String gid, String aid) { - this.members.add(aid); - } - public Group(List members, List messages, Accounts accounts) { - this.members = members; - this.messages = messages; - this.accounts = accounts; - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PULL-first/GroupChat.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PULL-first/GroupChat.java deleted file mode 100644 index 201f338..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PULL-first/GroupChat.java +++ /dev/null @@ -1,49 +0,0 @@ -import java.util.*; - -public class GroupChat { - private Accounts accounts; - private Groups groups; - public GroupChat() { - accounts = new Accounts(); - groups = new Groups(); - } - public List getMembers(String gid) { - return this.groups.getGroup(gid).getMembers(); - } - public void addGroupMember(String gid, String aid) { - this.groups.getGroup(gid).addGroupMember(gid, aid); - } - public Map getNotifications(String v1) { - return this.accounts.getAccount(m.get(mno)).getNotifications(); - } - public void hasRead(String aid, String gid) { - this.accounts.getAccount(aid).hasRead(aid, gid); - } - public Map getGroup(String gid) { - return this.groups.getGroup(gid).getValue(); - } - public List getMessages(String gid) { - return this.groups.getGroup(gid).getMessages(); - } - public void postMessage(String gid, String message) { - this.groups.getGroup(gid).postMessage(gid, message); - } - public Map getAccounts() { - return this.accounts.getValue(); - } - public void signUp(String aid) { - this.accounts.signUp(aid); - } - public Map getAccount(String v1) { - return this.accounts.getAccount(m.get(mno)).getValue(); - } - public Map getGroups() { - return this.groups.getValue(); - } - public void createGroup(String gid) { - this.groups.createGroup(gid); - } - public String getMember(String gid, int mno) { - return this.groups.getGroup(gid).getMember(mno); - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PULL-first/Groups.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PULL-first/Groups.java deleted file mode 100644 index 014bc27..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PULL-first/Groups.java +++ /dev/null @@ -1,14 +0,0 @@ -import java.util.*; - -public class Groups { - private Map value = new HashMap<>(); - public Map getValue() { - return new HashMap<>(value); - } - public Group getGroup(String gid) { - return this.value.get(gid); - } - public void createGroup(String gid) { - this.value.put(gid,new Group(new ArrayList<>(), new ArrayList<>(), accounts)); - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PUSH-first/Account.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PUSH-first/Account.java deleted file mode 100644 index 830c8ce..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PUSH-first/Account.java +++ /dev/null @@ -1,22 +0,0 @@ -import java.util.*; - -public class Account { - private Map notifications; - public Map getValue() { - Map temp_nil7 = new HashMap<>(); - temp_nil7.put("notifications",this.getNotifications()); - return temp_nil7; - } - public Map getNotifications() { - return new HashMap<>(notifications); - } - public void updateNotificationsFromMessages(String gid, int mno, List messages, String members) { - this.notifications.put(gid,true); - } - public void hasRead(String aid, String gid) { - this.notifications.remove(gid); - } - public Account(Map notifications) { - this.notifications = notifications; - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PUSH-first/Accounts.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PUSH-first/Accounts.java deleted file mode 100644 index 2e7c4e3..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PUSH-first/Accounts.java +++ /dev/null @@ -1,14 +0,0 @@ -import java.util.*; - -public class Accounts { - private Map value = new HashMap<>(); - public Map getValue() { - return new HashMap<>(value); - } - public Account getAccount(String v1) { - return this.value.get(v1); - } - public void signUp(String aid) { - this.value.put(aid,new Account(new HashMap<>())); - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PUSH-first/Group.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PUSH-first/Group.java deleted file mode 100644 index 660e433..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PUSH-first/Group.java +++ /dev/null @@ -1,39 +0,0 @@ -import java.util.*; - -public class Group { - private List members; - private List messages; - private Account account; - private Accounts accounts; - public Map getValue() { - Map temp_nil6 = new HashMap<>(); - temp_nil6.put("messages",this.getMessages()); - temp_nil6.put("members",this.getMembers()); - return temp_nil6; - } - public List getMembers() { - return this.members; - } - public List getMessages() { - return this.messages; - } - public String getMember(int mno) { - return this.members.get(mno); - } - public void postMessage(String gid, String message) { - this.messages.add(message); - for (int mno = 0; mno < this.members.size(); mno++) { - String member = getMember(mno); - this.account = accounts.getAccount(member); - this.account.updateNotificationsFromMessages(gid, mno, messages, member); - } - } - public void addGroupMember(String gid, String aid) { - this.members.add(aid); - } - public Group(List members, List messages, Accounts accounts) { - this.members = members; - this.messages = messages; - this.accounts = accounts; - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PUSH-first/GroupChat.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PUSH-first/GroupChat.java deleted file mode 100644 index 201f338..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PUSH-first/GroupChat.java +++ /dev/null @@ -1,49 +0,0 @@ -import java.util.*; - -public class GroupChat { - private Accounts accounts; - private Groups groups; - public GroupChat() { - accounts = new Accounts(); - groups = new Groups(); - } - public List getMembers(String gid) { - return this.groups.getGroup(gid).getMembers(); - } - public void addGroupMember(String gid, String aid) { - this.groups.getGroup(gid).addGroupMember(gid, aid); - } - public Map getNotifications(String v1) { - return this.accounts.getAccount(m.get(mno)).getNotifications(); - } - public void hasRead(String aid, String gid) { - this.accounts.getAccount(aid).hasRead(aid, gid); - } - public Map getGroup(String gid) { - return this.groups.getGroup(gid).getValue(); - } - public List getMessages(String gid) { - return this.groups.getGroup(gid).getMessages(); - } - public void postMessage(String gid, String message) { - this.groups.getGroup(gid).postMessage(gid, message); - } - public Map getAccounts() { - return this.accounts.getValue(); - } - public void signUp(String aid) { - this.accounts.signUp(aid); - } - public Map getAccount(String v1) { - return this.accounts.getAccount(m.get(mno)).getValue(); - } - public Map getGroups() { - return this.groups.getValue(); - } - public void createGroup(String gid) { - this.groups.createGroup(gid); - } - public String getMember(String gid, int mno) { - return this.groups.getGroup(gid).getMember(mno); - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PUSH-first/Groups.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PUSH-first/Groups.java deleted file mode 100644 index 014bc27..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/GroupChat/PUSH-first/Groups.java +++ /dev/null @@ -1,14 +0,0 @@ -import java.util.*; - -public class Groups { - private Map value = new HashMap<>(); - public Map getValue() { - return new HashMap<>(value); - } - public Group getGroup(String gid) { - return this.value.get(gid); - } - public void createGroup(String gid) { - this.value.put(gid,new Group(new ArrayList<>(), new ArrayList<>(), accounts)); - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/Account.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/Account.java new file mode 100644 index 0000000..f95e5e6 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/Account.java @@ -0,0 +1,33 @@ +import java.util.*; + +public class Account { + private String name; + private int point; + public Map getValue() { + Map temp_nil1 = new HashMap<>(); + temp_nil1.put("name",this.getName()); + temp_nil1.put("point",this.getPoint()); + return temp_nil1; + } + public String getName() { + return this.name; + } + public int getPoint() { + return point; + } + public void updatePointFromBattle(String self, String rid, int mno, boolean battle, String id) { + int temp_if0; + if (battle) { + temp_if0 = (this.point+1); + } else { + temp_if0 = this.point; + }this.point = temp_if0; + } + public void changeName(String aid, String name) { + this.name = name; + } + public Account(String name, int point) { + this.name = name; + this.point = point; + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/Accounts.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/Accounts.java new file mode 100644 index 0000000..6d92c89 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/Accounts.java @@ -0,0 +1,14 @@ +import java.util.*; + +public class Accounts { + private Map value = new HashMap<>(); + public Map getValue() { + return new HashMap<>(value); + } + public Account getAccount(String mid) { + return this.value.get(mid); + } + public void signUp(String name, String aid) { + this.value.put(aid,new Account(name, 0)); + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/Member.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/Member.java new file mode 100644 index 0000000..aac4c47 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/Member.java @@ -0,0 +1,23 @@ +import java.util.*; + +public class Member { + private String id; + private Account account; + private Accounts accounts; + public Map getValue() { + Map temp_nil2 = new HashMap<>(); + temp_nil2.put("name",this.getName()); + temp_nil2.put("id",this.getId()); + return temp_nil2; + } + public String getId() { + return this.id; + } + public String getName() { + return this.account.getName(); + } + public Member(String id, Accounts accounts) { + this.id = id; + this.accounts = accounts; + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/Members.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/Members.java new file mode 100644 index 0000000..091b561 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/Members.java @@ -0,0 +1,14 @@ +import java.util.*; + +public class Members { + private List value = new ArrayList<>(); + public List getValue() { + return new ArrayList<>(value); + } + public Member getMember(int mno) { + return this.value.get(mno); + } + public void addRoomMember(String rid, String id) { + this.value.add(new Member(id, accounts)); + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/OnlineBattleGame2.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/OnlineBattleGame2.java new file mode 100644 index 0000000..cc758ed --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/OnlineBattleGame2.java @@ -0,0 +1,58 @@ +import java.util.*; + +public class OnlineBattleGame2 { + private Accounts accounts; + private Rooms rooms; + public OnlineBattleGame2() { + accounts = new Accounts(); + rooms = new Rooms(accounts); + } + public boolean getBattle(String rid) { + return this.rooms.getRoom(rid).getBattle(); + } + public void battle(String rid, boolean hasWon) { + this.rooms.getRoom(rid).battle(rid, hasWon); + } + public Map getRoom(String rid) { + return this.rooms.getRoom(rid).getValue(); + } + public String getName(String mid) { + return this.accounts.getAccount(mid).getName(); + } + public void changeName(String aid, String name) { + this.accounts.getAccount(aid).changeName(aid, name); + } + public Map getAccounts() { + return this.accounts.getValue(); + } + public void signUp(String name, String aid) { + this.accounts.signUp(name, aid); + } + public List getMembers(String rid) { + return this.rooms.getRoom(rid).getMembers().getValue(); + } + public void addRoomMember(String rid, String id) { + this.rooms.getRoom(rid).getMembers().addRoomMember(rid, id); + } + public int getPoint(String mid) { + return this.accounts.getAccount(mid).getPoint(); + } + public Map getRooms() { + return this.rooms.getValue(); + } + public void createRoom(String rid) { + this.rooms.createRoom(rid); + } + public Map getAccount(String mid) { + return this.accounts.getAccount(mid).getValue(); + } + public Map getMember(String rid, int mno) { + return this.rooms.getRoom(rid).getMembers().getMember(mno).getValue(); + } + public String getId(String rid, int mno) { + return this.rooms.getRoom(rid).getMembers().getMember(mno).getId(); + } + public String getName(String rid, int mno) { + return this.rooms.getRoom(rid).getMembers().getMember(mno).getName(); + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/Account.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/Account.java deleted file mode 100644 index ecc737a..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/Account.java +++ /dev/null @@ -1,33 +0,0 @@ -import java.util.*; - -public class Account { - private String name; - private int point; - public Map getValue() { - Map temp_nil9 = new HashMap<>(); - temp_nil9.put("name",this.getName()); - temp_nil9.put("point",this.getPoint()); - return temp_nil9; - } - public String getName() { - return this.name; - } - public int getPoint() { - return point; - } - public void updatePointFromBattle(String self, String rid, int mno, boolean battle, String id) { - int temp_if0; - if (hasWon) { - temp_if0 = (this.point+1); - } else { - temp_if0 = this.point; - }this.point = temp_if0; - } - public void changeName(String aid, String name) { - this.name = name; - } - public Account(String name, int point) { - this.name = name; - this.point = point; - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/Accounts.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/Accounts.java deleted file mode 100644 index 6d92c89..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/Accounts.java +++ /dev/null @@ -1,14 +0,0 @@ -import java.util.*; - -public class Accounts { - private Map value = new HashMap<>(); - public Map getValue() { - return new HashMap<>(value); - } - public Account getAccount(String mid) { - return this.value.get(mid); - } - public void signUp(String name, String aid) { - this.value.put(aid,new Account(name, 0)); - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/Member.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/Member.java deleted file mode 100644 index 33658d5..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/Member.java +++ /dev/null @@ -1,23 +0,0 @@ -import java.util.*; - -public class Member { - private String id; - private Account account; - private Accounts accounts; - public Map getValue() { - Map temp_nil10 = new HashMap<>(); - temp_nil10.put("id",this.getId()); - temp_nil10.put("name",this.getName()); - return temp_nil10; - } - public String getId() { - return this.id; - } - public String getName() { - return this.account.getName(); - } - public Member(String id, Accounts accounts) { - this.id = id; - this.accounts = accounts; - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/Members.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/Members.java deleted file mode 100644 index 091b561..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/Members.java +++ /dev/null @@ -1,14 +0,0 @@ -import java.util.*; - -public class Members { - private List value = new ArrayList<>(); - public List getValue() { - return new ArrayList<>(value); - } - public Member getMember(int mno) { - return this.value.get(mno); - } - public void addRoomMember(String rid, String id) { - this.value.add(new Member(id, accounts)); - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/OnlineBattleGame2.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/OnlineBattleGame2.java deleted file mode 100644 index 69fc17e..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/OnlineBattleGame2.java +++ /dev/null @@ -1,58 +0,0 @@ -import java.util.*; - -public class OnlineBattleGame2 { - private Accounts accounts; - private Rooms rooms; - public OnlineBattleGame2() { - accounts = new Accounts(); - rooms = new Rooms(accounts); - } - public String getId(String rid, int mno) { - return this.rooms.getRoom(rid).getMembers().getMember(mno).getId(); - } - public Map getAccount(String mid) { - return this.accounts.getAccount(mid).getValue(); - } - public String getName(String mid) { - return this.accounts.getAccount(mid).getName(); - } - public void changeName(String aid, String name) { - this.accounts.getAccount(aid).changeName(aid, name); - } - public int getPoint(String mid) { - return this.accounts.getAccount(mid).getPoint(); - } - public Map getRoom(String rid) { - return this.rooms.getRoom(rid).getValue(); - } - public List getMembers(String rid) { - return this.rooms.getRoom(rid).getMembers().getValue(); - } - public void addRoomMember(String rid, String id) { - this.rooms.getRoom(rid).getMembers().addRoomMember(rid, id); - } - public String getName(String rid, int mno) { - return this.rooms.getRoom(rid).getMembers().getMember(mno).getName(); - } - public Map getMember(String rid, int mno) { - return this.rooms.getRoom(rid).getMembers().getMember(mno).getValue(); - } - public boolean getBattle(String rid) { - return this.rooms.getRoom(rid).getBattle(); - } - public void battle(String rid, boolean hasWon) { - this.rooms.getRoom(rid).battle(rid, hasWon); - } - public Map getAccounts() { - return this.accounts.getValue(); - } - public void signUp(String name, String aid) { - this.accounts.signUp(name, aid); - } - public Map getRooms() { - return this.rooms.getValue(); - } - public void createRoom(String rid) { - this.rooms.createRoom(rid); - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/Room.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/Room.java deleted file mode 100644 index ff4155c..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/Room.java +++ /dev/null @@ -1,32 +0,0 @@ -import java.util.*; - -public class Room { - private Members members = new Members(); - private boolean battle; - private Account account; - private Accounts accounts; - public Map getValue() { - Map temp_nil8 = new HashMap<>(); - temp_nil8.put("battle",this.getBattle()); - temp_nil8.put("members",this.members.getValue()); - return temp_nil8; - } - public Members getMembers() { - return this.members; - } - public boolean getBattle() { - return this.battle; - } - public void battle(String rid, boolean hasWon) { - this.battle = hasWon; - for (int mno = 0; mno < this.members.getValue().size(); mno++) { - String id = this.members.getMember(mno).getId(); - this.account = accounts.getAccount(id); - this.account.updatePointFromBattle(mid, rid, mno, battle, id); - } - } - public Room(boolean battle, Accounts accounts) { - this.battle = battle; - this.accounts = accounts; - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/Rooms.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/Rooms.java deleted file mode 100644 index d4230fa..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PULL-first/Rooms.java +++ /dev/null @@ -1,18 +0,0 @@ -import java.util.*; - -public class Rooms { - private Map value = new HashMap<>(); - private Accounts accounts; - public Map getValue() { - return new HashMap<>(value); - } - public Room getRoom(String rid) { - return this.value.get(rid); - } - public void createRoom(String rid) { - this.value.put(rid,new Room(false, accounts)); - } - public Rooms(Accounts accounts) { - this.accounts = accounts; - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/Account.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/Account.java deleted file mode 100644 index 5ad3e48..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/Account.java +++ /dev/null @@ -1,33 +0,0 @@ -import java.util.*; - -public class Account { - private int point; - private String name; - public Map getValue() { - Map temp_nil12 = new HashMap<>(); - temp_nil12.put("name",this.getName()); - temp_nil12.put("point",this.getPoint()); - return temp_nil12; - } - public int getPoint() { - return point; - } - public String getName() { - return this.name; - } - public void updatePointFromBattle(String self, String rid, int mno, boolean battle, String id) { - int temp_if1; - if (hasWon) { - temp_if1 = (this.point+1); - } else { - temp_if1 = this.point; - }this.point = temp_if1; - } - public void changeName(String aid, String name) { - this.name = name; - } - public Account(int point, String name) { - this.point = point; - this.name = name; - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/Accounts.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/Accounts.java deleted file mode 100644 index b5e61df..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/Accounts.java +++ /dev/null @@ -1,14 +0,0 @@ -import java.util.*; - -public class Accounts { - private Map value = new HashMap<>(); - public Map getValue() { - return new HashMap<>(value); - } - public Account getAccount(String mid) { - return this.value.get(mid); - } - public void signUp(String name, String aid) { - this.value.put(aid,new Account(0, name)); - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/Member.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/Member.java deleted file mode 100644 index 7e548af..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/Member.java +++ /dev/null @@ -1,27 +0,0 @@ -import java.util.*; - -public class Member { - private Account account; - private Accounts accounts; - private String id; - public Map getValue() { - Map temp_nil13 = new HashMap<>(); - temp_nil13.put("id",this.getId()); - temp_nil13.put("name",this.getName()); - return temp_nil13; - } - public String getName() { - return name; - } - public String getId() { - return this.id; - } - public void updateNameFromId(String self, int self2, String rid, int mno, String id) { - this.name = name; - this.id = id; - } - public Member(Accounts accounts, String id) { - this.accounts = accounts; - this.id = id; - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/Members.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/Members.java deleted file mode 100644 index dd86377..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/Members.java +++ /dev/null @@ -1,14 +0,0 @@ -import java.util.*; - -public class Members { - private List value = new ArrayList<>(); - public List getValue() { - return new ArrayList<>(value); - } - public Member getMember(int mno) { - return this.value.get(mno); - } - public void addRoomMember(String rid, String id) { - this.value.add(new Member(accounts, id)); - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/OnlineBattleGame2.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/OnlineBattleGame2.java deleted file mode 100644 index a2fbee5..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/OnlineBattleGame2.java +++ /dev/null @@ -1,58 +0,0 @@ -import java.util.*; - -public class OnlineBattleGame2 { - private Accounts accounts; - private Rooms rooms; - public OnlineBattleGame2() { - accounts = new Accounts(); - rooms = new Rooms(accounts); - } - public Map getAccount(String mid) { - return this.accounts.getAccount(mid).getValue(); - } - public int getPoint(String mid) { - return this.accounts.getAccount(mid).getPoint(); - } - public Map getRoom(String rid) { - return this.rooms.getRoom(rid).getValue(); - } - public List getMembers(String rid) { - return this.rooms.getRoom(rid).getMembers().getValue(); - } - public void addRoomMember(String rid, String id) { - this.rooms.getRoom(rid).getMembers().addRoomMember(rid, id); - } - public String getName(String rid, int mno) { - return this.rooms.getRoom(rid).getMembers().getMember(mno).getName(); - } - public String getId(String rid, int mno) { - return this.rooms.getRoom(rid).getMembers().getMember(mno).getId(); - } - public String getName(String mid) { - return this.accounts.getAccount(mid).getName(); - } - public void changeName(String aid, String name) { - this.accounts.getAccount(aid).changeName(aid, name); - } - public Map getMember(String rid, int mno) { - return this.rooms.getRoom(rid).getMembers().getMember(mno).getValue(); - } - public boolean getBattle(String rid) { - return this.rooms.getRoom(rid).getBattle(); - } - public void battle(String rid, boolean hasWon) { - this.rooms.getRoom(rid).battle(rid, hasWon); - } - public Map getAccounts() { - return this.accounts.getValue(); - } - public void signUp(String name, String aid) { - this.accounts.signUp(name, aid); - } - public Map getRooms() { - return this.rooms.getValue(); - } - public void createRoom(String rid) { - this.rooms.createRoom(rid); - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/Room.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/Room.java deleted file mode 100644 index ccc1b77..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/Room.java +++ /dev/null @@ -1,32 +0,0 @@ -import java.util.*; - -public class Room { - private Members members = new Members(); - private boolean battle; - private Account account; - private Accounts accounts; - public Map getValue() { - Map temp_nil11 = new HashMap<>(); - temp_nil11.put("battle",this.getBattle()); - temp_nil11.put("members",this.members.getValue()); - return temp_nil11; - } - public Members getMembers() { - return this.members; - } - public boolean getBattle() { - return this.battle; - } - public void battle(String rid, boolean hasWon) { - this.battle = hasWon; - for (int mno = 0; mno < this.members.getValue().size(); mno++) { - String id = this.members.getMember(mno).getId(); - this.account = accounts.getAccount(id); - this.account.updatePointFromBattle(mid, rid, mno, battle, id); - } - } - public Room(boolean battle, Accounts accounts) { - this.battle = battle; - this.accounts = accounts; - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/Rooms.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/Rooms.java deleted file mode 100644 index d4230fa..0000000 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/PUSH-first/Rooms.java +++ /dev/null @@ -1,18 +0,0 @@ -import java.util.*; - -public class Rooms { - private Map value = new HashMap<>(); - private Accounts accounts; - public Map getValue() { - return new HashMap<>(value); - } - public Room getRoom(String rid) { - return this.value.get(rid); - } - public void createRoom(String rid) { - this.value.put(rid,new Room(false, accounts)); - } - public Rooms(Accounts accounts) { - this.accounts = accounts; - } -} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/Room.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/Room.java new file mode 100644 index 0000000..43129a4 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/Room.java @@ -0,0 +1,32 @@ +import java.util.*; + +public class Room { + private Members members = new Members(); + private boolean battle; + private Account account; + private Accounts accounts; + public Map getValue() { + Map temp_nil0 = new HashMap<>(); + temp_nil0.put("members",this.members.getValue()); + temp_nil0.put("battle",this.getBattle()); + return temp_nil0; + } + public Members getMembers() { + return this.members; + } + public boolean getBattle() { + return this.battle; + } + public void battle(String rid, boolean hasWon) { + this.battle = hasWon; + for (int mno = 0; mno < this.members.getValue().size(); mno++) { + String id = this.members.getMember(mno).getId(); + this.account = accounts.getAccount(id); + this.account.updatePointFromBattle(id, rid, mno, battle, id); + } + } + public Room(boolean battle, Accounts accounts) { + this.battle = battle; + this.accounts = accounts; + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/Rooms.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/Rooms.java new file mode 100644 index 0000000..d4230fa --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/OnlineBattleGame2/Rooms.java @@ -0,0 +1,18 @@ +import java.util.*; + +public class Rooms { + private Map value = new HashMap<>(); + private Accounts accounts; + public Map getValue() { + return new HashMap<>(value); + } + public Room getRoom(String rid) { + return this.value.get(rid); + } + public void createRoom(String rid) { + this.value.put(rid,new Room(false, accounts)); + } + public Rooms(Accounts accounts) { + this.accounts = accounts; + } +} \ No newline at end of file diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/VotingSystem/Account.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/VotingSystem/Account.java index 7dec970..605d6c1 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/VotingSystem/Account.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/VotingSystem/Account.java @@ -3,9 +3,9 @@ public class Account { private String vote; public Map getValue() { - Map temp_nil1 = new HashMap<>(); - temp_nil1.put("vote",this.getVote()); - return temp_nil1; + Map temp_nil4 = new HashMap<>(); + temp_nil4.put("vote",this.getVote()); + return temp_nil4; } public String getVote() { return this.vote; diff --git a/AlgebraicDataflowArchitectureModel/prototypes/Java/VotingSystem/VotingSystem.java b/AlgebraicDataflowArchitectureModel/prototypes/Java/VotingSystem/VotingSystem.java index 50ae847..27950ce 100644 --- a/AlgebraicDataflowArchitectureModel/prototypes/Java/VotingSystem/VotingSystem.java +++ b/AlgebraicDataflowArchitectureModel/prototypes/Java/VotingSystem/VotingSystem.java @@ -1,14 +1,11 @@ import java.util.*; public class VotingSystem { - private Counts counts; private Accounts accounts; + private Counts counts; public VotingSystem() { - counts = new Counts(); accounts = new Accounts(); - } - public Map getCounts() { - return this.counts.getValue(); + counts = new Counts(accounts); } public Map getAccount(String aid) { return this.accounts.getAccount(aid).getValue(); @@ -19,6 +16,9 @@ public void signUp(String name, String aid) { this.accounts.signUp(name, aid); } + public Map getCounts() { + return this.counts.getValue(); + } public String getVote(String aid) { return this.accounts.getAccount(aid).getVote(); } diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java index 4083dce..846c273 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/JavaPrototypeGenerateAction.java @@ -18,6 +18,7 @@ import generators.JavaCodeGenerator; import generators.JavaMethodBodyGenerator; import generators.JavaSpecific; +import generators.StandaloneSpecific; import models.dataConstraintModel.ResourceHierarchy; import models.dataConstraintModel.ResourcePath; import models.dataFlowModel.DataTransferModel; @@ -59,8 +60,8 @@ } else { JavaCodeGenerator.resetMainTypeName(); // use the default main type's name. } - editor.setCodes(JavaMethodBodyGenerator.doGenerate(graph, model, JavaCodeGenerator.doGenerate(graph, model))); -// editor.setCodes(new CodeGeneratorFromDataFlowGraph().generateCode(model, graph, new JavaSpecific())); +// editor.setCodes(JavaMethodBodyGenerator.doGenerate(graph, model, JavaCodeGenerator.doGenerate(graph, model))); + editor.setCodes(new CodeGeneratorFromDataFlowGraph().generateCode(model, graph, new StandaloneSpecific(), new JavaSpecific())); ModelExtension.recoverModel(model); for (CompilationUnit file : editor.getCodes()) { System.out.println(file); diff --git a/AlgebraicDataflowArchitectureModel/src/application/actions/JerseyPrototypeGenerateAction.java b/AlgebraicDataflowArchitectureModel/src/application/actions/JerseyPrototypeGenerateAction.java index dbf75fd..da1a3df 100644 --- a/AlgebraicDataflowArchitectureModel/src/application/actions/JerseyPrototypeGenerateAction.java +++ b/AlgebraicDataflowArchitectureModel/src/application/actions/JerseyPrototypeGenerateAction.java @@ -1,10 +1,8 @@ package application.actions; import java.awt.event.ActionEvent; -import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; -import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; @@ -13,12 +11,13 @@ import algorithms.*; import application.editor.Editor; import code.ast.*; +import generators.CodeGeneratorFromDataFlowGraph; import generators.DataTransferMethodAnalyzer; +import generators.JavaSpecific; import generators.JerseyCodeGenerator; import generators.JerseyMethodBodyGenerator; -import models.algebra.Type; +import generators.JerseySpecific; import models.dataConstraintModel.ResourceHierarchy; -import models.dataConstraintModel.ResourcePath; import models.dataFlowModel.DataTransferModel; import models.dataFlowModel.ModelExtension; import models.dataFlowModel.DataFlowGraph; @@ -58,7 +57,8 @@ } else { JerseyCodeGenerator.resetMainTypeName(); // use the default main type's name. } - editor.setCodes(JerseyMethodBodyGenerator.doGenerate(graph, model, JerseyCodeGenerator.doGenerate(graph, model))); +// editor.setCodes(JerseyMethodBodyGenerator.doGenerate(graph, model, JerseyCodeGenerator.doGenerate(graph, model))); + editor.setCodes(new CodeGeneratorFromDataFlowGraph().generateCode(model, graph, new JerseySpecific(), new JavaSpecific())); ModelExtension.recoverModel(model); for (CompilationUnit file : editor.getCodes()) { System.out.println(file); diff --git a/AlgebraicDataflowArchitectureModel/src/code/ast/CodeUtil.java b/AlgebraicDataflowArchitectureModel/src/code/ast/CodeUtil.java index 99f1561..fd57c66 100644 --- a/AlgebraicDataflowArchitectureModel/src/code/ast/CodeUtil.java +++ b/AlgebraicDataflowArchitectureModel/src/code/ast/CodeUtil.java @@ -10,34 +10,4 @@ } return newString; } - - public static String getToStringExp(String typeName, String rawExp) { - if (typeName.equals("int")) { - return "Integer.toString(" + rawExp + ")"; - } else if (typeName.equals("float")) { - return "Float.toString(" + rawExp + ")"; - } else if (typeName.equals("double")) { - return "Double.toString(" + rawExp + ")"; - } else if (typeName.equals("boolean")) { - return "Boolean.toString(" + rawExp + ")"; - } else { - return rawExp + ".toString()"; - } - } - - public static String getToValueExp(String typeName, String strExp) { - if (typeName.equals("int")) { - return "Integer.parseInt(" + strExp + ")"; - } else if (typeName.equals("float")) { - return "Float.parseFloat(" + strExp + ")"; - } else if (typeName.equals("double")) { - return "Double.parseDouble(" + strExp + ")"; - } else if (typeName.equals("boolean")) { - return "Boolean.parseBoolean(" + strExp + ")"; - } else if (typeName.startsWith("ArrayList") || typeName.startsWith("List")) { - return "Arrays.asList(" + strExp + ".replace(\"[\",\"\").replace(\"]\",\"\").split(\",\",0))"; - } else { - return strExp; - } - } } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java index 015baa7..b23a6a3 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGenerator.java @@ -10,6 +10,7 @@ import java.util.Set; import java.util.Stack; +import algorithms.TypeInference; import code.ast.Block; import code.ast.CompilationUnit; import code.ast.FieldDeclaration; @@ -50,8 +51,9 @@ */ public abstract class CodeGenerator { public static final String fieldOfResourceState = "value"; + public static final String methoNameOfResourceState = "Value"; public static final String getterPrefix = "get"; - public static final String getterOfResourceState = "getValue"; + public static final String getterOfResourceState = getterPrefix + methoNameOfResourceState; // "getValue" public static final String updateMethodPrefix = "update"; public static final String from = "From"; public static final String _for = "For"; @@ -167,16 +169,9 @@ private static Map> getDependedRootComponentGraph(DataTransferModel model) { Map> dependedComponentGraph = new HashMap<>(); for (Channel ch: model.getChannels()) { - DataTransferChannel dtCh = (DataTransferChannel) ch; Set inRes = new HashSet<>(); Set outRes = new HashSet<>(); - for (ChannelMember cm: dtCh.getChannelMembers()) { - if (cm.isOutside()) { - outRes.add(cm.getResource().getResourceHierarchy()); - } else { - inRes.add(cm.getResource().getResourceHierarchy()); - } - } + getDependedRootComponentGraphSub(ch, inRes, outRes, true); if (outRes.size() > 0 && inRes.size() > 0) { for (ResourceHierarchy out: outRes) { for (ResourceHierarchy in: inRes) { @@ -185,13 +180,32 @@ dependings = new HashSet<>(); dependedComponentGraph.put(out.getRoot(), dependings); } - dependings.add(in.getRoot()); + if (!out.getRoot().equals(in.getRoot())) { + dependings.add(in.getRoot()); + } } } } } return dependedComponentGraph; } + + private static void getDependedRootComponentGraphSub(Channel ch, Set inRes, Set outRes, boolean isRoot) { + DataTransferChannel dtCh = (DataTransferChannel) ch; + for (ChannelMember cm: dtCh.getChannelMembers()) { + if (!isRoot && !cm.isOutside()) { + outRes.add(cm.getResource().getResourceHierarchy()); // dependency to a descendant channel resource. + } + if (cm.isOutside()) { + outRes.add(cm.getResource().getResourceHierarchy()); // dependency to an outside resource. + } else { + inRes.add(cm.getResource().getResourceHierarchy()); // dependency from an inside resource. + } + } + for (Channel childCh: ch.getChildren()) { + getDependedRootComponentGraphSub(childCh, inRes, outRes, false); + } + } private static ArrayList determineComponentOrder(DataFlowGraph graph, Map> dependedRootComponentGraph) { ArrayList objects = new ArrayList<>(); @@ -286,7 +300,9 @@ } if (constructor.getParameters() != null) { for (VariableDeclaration var: constructor.getParameters()) { - parameters.add(var.getName()); + if (!parameters.contains(var.getName())) { + parameters.add(var.getName()); + } } } @@ -316,26 +332,36 @@ return dstRes; } - protected void fillStateGetterMethod(MethodDeclaration stateGetter, ResourceHierarchy resourceHierarchy, Type resStateType, ILanguageSpecific langSpec) { + protected void fillStateGetterMethod(MethodDeclaration stateGetter, ResourceHierarchy resourceHierarchy, Type resStateType, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { // returns the state field when all incoming data-flow edges are PUSH-style. if (langSpec.isValueType(resStateType)) { stateGetter.addStatement(langSpec.getReturnStatement(langSpec.getFieldAccessor(fieldOfResourceState)) + langSpec.getStatementDelimiter()); // return value; } else { if (resourceHierarchy.getChildren() != null && resourceHierarchy.getChildren().size() == 1 && resourceHierarchy.getChildren().iterator().next().getNumParameters() > 0) { // list or map - String implTypeName = resStateType.getImplementationTypeName(); - // copy the current state to be returned as a 'value' - List parameters = new ArrayList<>(); - parameters.add(langSpec.getFieldAccessor(fieldOfResourceState)); - stateGetter.addStatement(langSpec.getReturnStatement(langSpec.getConstructorInvocation(implTypeName, parameters)) + langSpec.getStatementDelimiter()); // return new Resource(value); - } else { - if (resourceHierarchy.getChildren() == null || resourceHierarchy.getChildren().size() == 0) { - // a leaf resource +// if (!platformSpec.isMonolithic()) { +// // For REST API +// stateGetter.addStatement(langSpec.getReturnStatement(langSpec.getFieldAccessor(fieldOfResourceState)) + langSpec.getStatementDelimiter()); // return value; +// } else { String implTypeName = resStateType.getImplementationTypeName(); // copy the current state to be returned as a 'value' List parameters = new ArrayList<>(); parameters.add(langSpec.getFieldAccessor(fieldOfResourceState)); stateGetter.addStatement(langSpec.getReturnStatement(langSpec.getConstructorInvocation(implTypeName, parameters)) + langSpec.getStatementDelimiter()); // return new Resource(value); +// } + } else { + if (resourceHierarchy.getChildren() == null || resourceHierarchy.getChildren().size() == 0) { +// // a leaf resource +// if (!platformSpec.isMonolithic()) { +// // For REST API +// stateGetter.addStatement(langSpec.getReturnStatement(langSpec.getFieldAccessor(fieldOfResourceState)) + langSpec.getStatementDelimiter()); // return value; +// } else { + String implTypeName = resStateType.getImplementationTypeName(); + // copy the current state to be returned as a 'value' + List parameters = new ArrayList<>(); + parameters.add(langSpec.getFieldAccessor(fieldOfResourceState)); + stateGetter.addStatement(langSpec.getReturnStatement(langSpec.getConstructorInvocation(implTypeName, parameters)) + langSpec.getStatementDelimiter()); // return new Resource(value); +// } } else { Term composer = null; Term composerSub = new Constant(DataConstraintModel.nil); @@ -344,10 +370,10 @@ String childTypeName = getComponentName(child, langSpec); String fieldName = langSpec.toVariableName(childTypeName); Term childGetter = null; - if (!CodeGenerator.generatesComponent(child)) { + if (!generatesComponent(child)) { // the child is not a class - childGetter = new Term(new Symbol("get" + childTypeName, 1, Symbol.Type.METHOD)); - childGetter.addChild(new Constant("this")); + childGetter = new Term(new Symbol(getterPrefix + childTypeName, 1, Symbol.Type.METHOD)); + childGetter.addChild(new Constant(langSpec.getSelfExp())); } else { // the child is a class childGetter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); @@ -408,7 +434,7 @@ } } - protected void declareAccessorInMainComponent(TypeDeclaration mainComponent, ResourceNode accessRes, MethodDeclaration stateGetter, ILanguageSpecific langSpec) { + protected void declareAccessorInMainComponent(TypeDeclaration mainComponent, ResourceNode accessRes, MethodDeclaration stateGetter, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { List mainGetterParams = new ArrayList<>(); int v = 1; for (Expression param: accessRes.getPrimaryResourcePath().getPathParams()) { @@ -421,6 +447,11 @@ } v++; } + ResourcePath accessResPath = new ResourcePath(accessRes.getPrimaryResourcePath()); + for (int i = 0; i < mainGetterParams.size(); i++) { + Parameter pathParam = new Parameter(mainGetterParams.get(i).getName()); + accessResPath.replacePathParam(i, pathParam, null); + } MethodDeclaration accessor = null; if (mainGetterParams.size() == 0) { accessor = langSpec.newMethodDeclaration(getterPrefix + getComponentName(accessRes.getResourceHierarchy(), langSpec), getImplStateType(accessRes.getResourceHierarchy(), langSpec)); @@ -428,7 +459,7 @@ accessor = langSpec.newMethodDeclaration(getterPrefix + getComponentName(accessRes.getResourceHierarchy(), langSpec), false, getImplStateType(accessRes.getResourceHierarchy(), langSpec), mainGetterParams); } Block block = new Block(); - Expression getState = getPullAccessor().getDirectStateAccessorFor(accessRes.getPrimaryResourcePath(), null); + Expression getState = getPullAccessor(platformSpec).getDirectStateAccessorFor(accessResPath, null); block.addStatement(langSpec.getReturnStatement(getState.toImplementation(new String[] {null})) + langSpec.getStatementDelimiter()); // if (stateGetter.getParameters() == null || stateGetter.getParameters().size() == 0) { // block.addStatement(langSpec.getReturnStatement(langSpec.getMethodInvocation(accessRes.getResourceName(), stateGetter.getName())) + langSpec.getStatementDelimiter()); @@ -505,252 +536,740 @@ } return input; } + + + protected MethodDeclaration getMethod(TypeDeclaration component, String methodName, List params) { + for (MethodDeclaration m: component.getMethods()) { + if (m.getName().equals(methodName)) { + if (m.getParameters() == null && (params == null || params.size() == 0)) return m; + if (m.getParameters() != null && params != null && m.getParameters().size() == params.size()) { + boolean matchParams = true; + for (int i = 0; i < m.getParameters().size(); i++) { + if (!m.getParameters().get(i).getType().equals(params.get(i).getType())) { + matchParams = false; + break; + } + } + if (matchParams) return m; + } + } + } + return null; + } protected MethodDeclaration getMethod(TypeDeclaration component, String methodName) { for (MethodDeclaration m: component.getMethods()) { if (m.getName().equals(methodName)) return m; } return null; + } + + protected boolean isPut(ChannelMember cm) { + return cm.getStateTransition().isRightUnary(); } - protected IResourceStateAccessor getPushAccessor() { - return new IResourceStateAccessor() { - @Override - public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes= target.getResource(); - ResourcePath fromRes= from.getResource(); - if (targetRes.equals(fromRes)) { - return new Field(fieldOfResourceState, + protected boolean isDelete(ChannelMember cm) { + boolean isDelete = false; + Expression nextExp = cm.getStateTransition().getNextStateExpression(); + if (nextExp instanceof Term) { + Symbol rootSymbol = ((Term) nextExp).getSymbol(); + if (rootSymbol.equals(DataConstraintModel.delete) || rootSymbol.equals(DataConstraintModel.remove)) { + isDelete = true; + } else if (rootSymbol.equals(DataConstraintModel.cond)) { + Expression childExp = ((Term) nextExp).getChild(1); + if (childExp instanceof Term) { + rootSymbol = ((Term) childExp).getSymbol(); + if (rootSymbol.equals(DataConstraintModel.delete) || rootSymbol.equals(DataConstraintModel.remove)) { + isDelete = true; + } + } + childExp = ((Term) nextExp).getChild(2); + if (childExp instanceof Term) { + rootSymbol = ((Term) childExp).getSymbol(); + if (rootSymbol.equals(DataConstraintModel.delete) || rootSymbol.equals(DataConstraintModel.remove)) { + isDelete = true; + } + } + } + } + return isDelete; + } + + protected String getGetterResourcePathAndPathParams(ResourcePath resPath, List pathParams, + IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + int v = 1; + List params = new ArrayList<>(); + for (Expression pathParam: resPath.getPathParams()) { + if (pathParam instanceof Variable) { + Variable var = (Variable) pathParam; + String paramName = var.getName(); + params.add("{" + paramName + "}"); + VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), paramName); + if (!platformSpec.isMonolithic()) ((RestApiSpecific) platformSpec).addPathParamAnnotation(param, paramName); + pathParams.add(param); + } else if (pathParam instanceof Term) { + Term var = (Term) pathParam; + String paramName = "v" + v; + params.add("{" + paramName + "}"); + VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), paramName); + if (!platformSpec.isMonolithic()) ((RestApiSpecific) platformSpec).addPathParamAnnotation(param, paramName); + pathParams.add(param); + } + } + return resPath.getResourceHierarchy().toResourcePath(params); + } + + protected String getUpdateResourcePathAndPathParams(ResourcePath resPath, ArrayList pathParams, boolean isRestAPI, + IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + int v = 1; + List params = new ArrayList<>(); + for (Expression pathParam: resPath.getPathParams()) { + if (pathParam instanceof Variable) { + Variable var = (Variable) pathParam; + String paramName = null; + if (isRestAPI) { + paramName = var.getName(); + } else { + paramName = "self" + (v > 1 ? v : ""); + } + params.add("{" + paramName + "}"); + VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), paramName); + if (isRestAPI) ((RestApiSpecific) platformSpec).addPathParamAnnotation(param, paramName); + pathParams.add(param); + } else if (pathParam instanceof Term) { + Term var = (Term) pathParam; + String paramName = null; + if (isRestAPI) { + paramName = "v" + v; + } else { + paramName = "self" + (v > 1 ? v : ""); + } + params.add("{" + paramName + "}"); + VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), paramName); + if (isRestAPI) ((RestApiSpecific) platformSpec).addPathParamAnnotation(param, paramName); + pathParams.add(param); + } + v++; + } + return resPath.getResourceHierarchy().toResourcePath(params); + } + + protected String getInputMethodResourcePathAndPathParams(ResourcePath resPath, ArrayList rootInputParams, + IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + int v = 1; + List params = new ArrayList<>(); + if (resPath.getLastParam() != null) { + Expression pathParam = resPath.getLastParam(); + if (pathParam instanceof Variable) { + Variable var = (Variable) pathParam; + String paramName = var.getName(); + params.add("{" + paramName + "}"); + VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), paramName); + if (!platformSpec.isMonolithic()) ((RestApiSpecific) platformSpec).addPathParamAnnotation(param, paramName); + rootInputParams.add(param); + } else if (pathParam instanceof Term) { + Term var = (Term) pathParam; + String paramName = "v" + v; + params.add("{" + paramName + "}"); + VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), paramName); + if (!platformSpec.isMonolithic()) ((RestApiSpecific) platformSpec).addPathParamAnnotation(param, paramName); + rootInputParams.add(param); + } + v++; + } + if (resPath.getParent() != null) { + for (Expression pathParam: resPath.getParent().getPathParams()) { + if (pathParam instanceof Variable) { + Variable var = (Variable) pathParam; + String paramName = var.getName(); + params.add("{" + paramName + "}"); + VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), paramName); + if (!platformSpec.isMonolithic()) ((RestApiSpecific) platformSpec).addPathParamAnnotation(param, paramName); + rootInputParams.add(param); + } else if (pathParam instanceof Term) { + Term var = (Term) pathParam; + String paramName = "v" + v; + params.add("{" + paramName + "}"); + VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), paramName); + if (!platformSpec.isMonolithic()) ((RestApiSpecific) platformSpec).addPathParamAnnotation(param, paramName); + rootInputParams.add(param); + } + v++; + } + } + return resPath.getResourceHierarchy().toResourcePath(params); + } + + protected void generatePullDataTransfer(MethodDeclaration methodBody, String fromResourceName, String fromResourcePath, Type fromResourceType, boolean doesAddFirst, + IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + RestApiSpecific restApiSpec = (RestApiSpecific) platformSpec; + String varName = new String(fromResourceName); + String respTypeName = fromResourceType.getInterfaceTypeName(); + String respImplTypeName = fromResourceType.getImplementationTypeName(); + String respConverter = ""; + if (DataConstraintModel.typeList.isAncestorOf(fromResourceType) && fromResourceType != DataConstraintModel.typeList) { + Type compType = TypeInference.getListComponentType(fromResourceType); + if (DataConstraintModel.typeTuple.isAncestorOf(compType)) { + varName += "_json"; + String mapTypeName = convertFromEntryToMapType(compType, langSpec); + respTypeName = langSpec.newListType(mapTypeName).getInterfaceTypeName(); + respConverter += langSpec.getVariableDeclaration(fromResourceType.getInterfaceTypeName(), fromResourceName) + langSpec.getAssignment() + langSpec.getConstructorInvocation(fromResourceType.getImplementationTypeName(), null) + langSpec.getStatementDelimiter() + "\n"; + respConverter += langSpec.getForStatementForCollection("i", mapTypeName, varName) + "\n"; + respConverter += "\t" + langSpec.getMethodInvocation(fromResourceName, DataConstraintModel.append.getImplName(), List.of(getCodeForConversionFromMapToTuple(compType, "i", langSpec))) + langSpec.getStatementDelimiter() + "\n"; + respConverter += langSpec.getEndForStatement("i") ; + restApiSpec.addJsonException(methodBody); + } else if (DataConstraintModel.typeMap.isAncestorOf(compType)) { + // To do. + } + } else if (DataConstraintModel.typeTuple.isAncestorOf(fromResourceType)) { + varName += "_json"; + respTypeName = convertFromEntryToMapType(fromResourceType, langSpec); + respConverter += langSpec.getVariableDeclaration(fromResourceType.getInterfaceTypeName(), fromResourceName) + langSpec.getAssignment() + getCodeForConversionFromMapToTuple(fromResourceType, varName, langSpec) + langSpec.getStatementDelimiter(); + respImplTypeName = "HashMap"; + } else if (DataConstraintModel.typePair.isAncestorOf(fromResourceType)) { + varName += "_json"; + respTypeName = convertFromEntryToMapType(fromResourceType, langSpec); + respConverter += langSpec.getVariableDeclaration(fromResourceType.getInterfaceTypeName(), fromResourceName) + langSpec.getAssignment() + getCodeForConversionFromMapToPair(fromResourceType, varName, langSpec) + langSpec.getStatementDelimiter(); + respImplTypeName = "HashMap"; + } else if (DataConstraintModel.typeMap.isAncestorOf(fromResourceType)) { + varName += "_json"; + respTypeName = convertFromEntryToMapType(fromResourceType, langSpec); + respConverter += langSpec.getVariableDeclaration(fromResourceType.getInterfaceTypeName(), fromResourceName) + langSpec.getAssignment() + langSpec.getConstructorInvocation(fromResourceType.getImplementationTypeName(), null) + langSpec.getStatementDelimiter() + "\n"; + respConverter += getCodeForConversionFromMapToMap(fromResourceType, varName, fromResourceName, langSpec); + respImplTypeName = "HashMap"; + } + if (doesAddFirst) { + if (respConverter.length() > 0) { + methodBody.addFirstStatement(respConverter); + } + methodBody.addFirstStatement(langSpec.getVariableDeclaration(respTypeName, varName) + langSpec.getAssignment() + restApiSpec.getHttpMethodCallWithResponseStatement(restApiSpec.getBaseURL(), fromResourcePath, getterPrefix, respImplTypeName)); + } else { + methodBody.addStatement(langSpec.getVariableDeclaration(respTypeName, varName) + langSpec.getAssignment() + restApiSpec.getHttpMethodCallWithResponseStatement(restApiSpec.getBaseURL(), fromResourcePath, getterPrefix, respImplTypeName)); + if (respConverter.length() > 0) { + methodBody.addStatement(respConverter); + } + } + } + + protected String convertFromEntryToMapType(Type type, ILanguageSpecific langSpec) { + String mapTypeName = null; + if (DataConstraintModel.typePair.isAncestorOf(type)) { + Type compType = TypeInference.getPairComponentType(type); + String wrapperType = DataConstraintModel.getWrapperType(compType); + if (wrapperType != null) { + mapTypeName = langSpec.newMapType(DataConstraintModel.typeString, wrapperType).getInterfaceTypeName(); + } else { + mapTypeName = langSpec.newMapType(DataConstraintModel.typeString, compType.getInterfaceTypeName()).getInterfaceTypeName(); + } + } else if (DataConstraintModel.typeMap.isAncestorOf(type)) { + List compTypes = TypeInference.getMapComponentTypes(type); + String wrapperType = DataConstraintModel.getWrapperType(compTypes.get(1)); + if (wrapperType != null) { + mapTypeName = langSpec.newMapType(DataConstraintModel.typeString, wrapperType).getInterfaceTypeName(); + } else { + mapTypeName = langSpec.newMapType(DataConstraintModel.typeString, compTypes.get(1).getInterfaceTypeName()).getInterfaceTypeName(); + } + } else { + mapTypeName = type.getInterfaceTypeName(); + mapTypeName = mapTypeName.replace(DataConstraintModel.typeTuple.getInterfaceTypeName(), DataConstraintModel.typeMap.getInterfaceTypeName()); + for (int idx = mapTypeName.indexOf("<", 0); idx >= 0; idx = mapTypeName.indexOf("<", idx + 1)) { // Java specific + int to = mapTypeName.indexOf(",", idx); // Java specific + if (to > idx) { + mapTypeName = mapTypeName.substring(0, idx + 1) + DataConstraintModel.typeString.getInterfaceTypeName() + mapTypeName.substring(to); // All elements except for the last one have the string type. + } + } + } + return mapTypeName; + } + + protected String getCodeForConversionFromMapToTuple(Type tupleType, String mapVar, ILanguageSpecific langSpec) { + String decoded = "$x"; + List elementsTypes = TypeInference.getTupleComponentTypes(tupleType); + String elementBase = mapVar; + for (Type elmType: elementsTypes.subList(0, elementsTypes.size() - 1)) { + elementBase = langSpec.getFirstEntryFromMapExp(elementBase); // elementBase.entrySet().iterator().next() + if (elmType == DataConstraintModel.typeBoolean + || elmType == DataConstraintModel.typeInt + || elmType == DataConstraintModel.typeLong + || elmType == DataConstraintModel.typeFloat + || elmType == DataConstraintModel.typeDouble) { + String getKey = langSpec.getMethodInvocation(elementBase, DataConstraintModel.fst.getImplName()); // elementBase.getKey() + String elmVal = langSpec.getStringToValueExp(elmType.getImplementationTypeName(), getKey); // Integer.parseInt(elementBase.getKey()) + decoded = decoded.replace("$x", langSpec.getPairExp(elmVal, "$x")); // new AbstractMap.SimpleEntry<>(Integer.parseInt(elementBase.getKey()), $x) + } else if (elmType == DataConstraintModel.typeString) { + String getKey = langSpec.getMethodInvocation(elementBase, DataConstraintModel.fst.getImplName()); // elementBase.getKey() + decoded = decoded.replace("$x", langSpec.getPairExp(getKey, "$x")); // new AbstractMap.SimpleEntry<>(elementBase.getKey(), $x) + } else { + // To do. + } + elementBase = langSpec.getMethodInvocation(elementBase, DataConstraintModel.snd.getImplName()); // elementBase.getValue() + } + decoded = decoded.replace("$x", elementBase); + return decoded; + } + + protected String getCodeForConversionFromMapToPair(Type pairType, String mapVar, ILanguageSpecific langSpec) { + String decoded = "$x"; + decoded = decoded.replace("$x", "new Pair<>(" + mapVar + ".get(\"left\"), $x)"); + decoded = decoded.replace("$x", mapVar + ".get(\"right\")"); + return decoded; + } + + protected String getCodeForConversionFromMapToMap(Type mapType, String mapVal, String mapVar, ILanguageSpecific langSpec) { + List elementsTypes = TypeInference.getMapComponentTypes(mapType); + Type keyType = elementsTypes.get(0); +// Type valType = elementsTypes.get(1); + String decoded = ""; + if (keyType == DataConstraintModel.typeBoolean + || keyType == DataConstraintModel.typeInt + || keyType == DataConstraintModel.typeLong + || keyType == DataConstraintModel.typeFloat + || keyType == DataConstraintModel.typeDouble) { + String keyVal = langSpec.getStringToValueExp(keyType.getImplementationTypeName(), "k"); + String getInvocation = langSpec.getMethodInvocation(mapVal, DataConstraintModel.lookup.getImplName(), List.of(keyVal)); + decoded += langSpec.getForStatementForMap("k", DataConstraintModel.typeString.getInterfaceTypeName(), mapVal) + "\n"; + decoded += "\t" + langSpec.getMethodInvocation(mapVar, DataConstraintModel.insert.getImplName(), List.of(keyVal, getInvocation)) + langSpec.getStatementDelimiter() + "\n"; + decoded += langSpec.getEndForStatement("k"); + } else if (keyType == DataConstraintModel.typeString) { + decoded += mapVar + langSpec.getAssignment() + mapVal + langSpec.getStatementDelimiter(); + } + return decoded; + } + + protected IResourceStateAccessor getPushAccessor(IPlatformSpecific platformSpec) { + if (platformSpec.isMonolithic()) { + return new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes= target.getResource(); + ResourcePath fromRes= from.getResource(); + if (targetRes.equals(fromRes)) { + return new Field(fieldOfResourceState, + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + // use the cached value as the current state + return new Field(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } - // use the cached value as the current state - return new Field(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - - @Override - public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes= target.getResource(); - return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - - @Override - public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { - if (fromRes != null && targetRes.equals(fromRes)) { - return new Field(fieldOfResourceState, + + @Override + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes= target.getResource(); + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } - // for reference channel member - return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - }; + + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { + if (fromRes != null && targetRes.equals(fromRes)) { + return new Field(fieldOfResourceState, + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + // for reference channel member + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + }; + } else { + return new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + ResourcePath fromRes = from.getResource(); + if (targetRes.equals(fromRes)) { + return new Field(fieldOfResourceState, + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + // use the cached value as the current state + return new Field(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + + @Override + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { + if (fromRes != null && targetRes.equals(fromRes)) { + return new Field(fieldOfResourceState, + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + return null; + } + }; + } } - protected IResourceStateAccessor getPullAccessor() { - return new IResourceStateAccessor() { - @Override - public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes= target.getResource(); - if (from != null) { - ResourcePath fromRes= from.getResource(); - if (!target.isOutside()) { - return getDirectStateAccessorFor(targetRes, fromRes); - } - Term getter = null; - String targetComponentName = getComponentName(targetRes.getResourceHierarchy(), langSpec); - if (generatesComponent(targetRes.getResourceHierarchy())) { - getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); - getter.addChild(new Field(langSpec.toVariableName(targetComponentName), targetRes.getResourceStateType())); + protected IResourceStateAccessor getPullAccessor(IPlatformSpecific platformSpec) { + if (platformSpec.isMonolithic()) { + return new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes= target.getResource(); + if (from != null) { + ResourcePath fromRes= from.getResource(); + if (!target.isOutside()) { + return getDirectStateAccessorFor(targetRes, fromRes); + } + Term getter = null; + String targetComponentName = getComponentName(targetRes.getResourceHierarchy(), langSpec); + if (generatesComponent(targetRes.getResourceHierarchy())) { + getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(langSpec.toVariableName(targetComponentName), targetRes.getResourceStateType())); + } else { + String parentName = langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy().getParent(), langSpec)); + Type parentType = targetRes.getResourceHierarchy().getParent().getResourceStateType(); + getter = new Term(new Symbol(getterPrefix + targetComponentName, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(parentName, parentType)); + } + return getter; } else { - String parentName = langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy().getParent(), langSpec)); - Type parentType = targetRes.getResourceHierarchy().getParent().getResourceStateType(); - getter = new Term(new Symbol(getterPrefix + targetComponentName, 1, Symbol.Type.METHOD)); - getter.addChild(new Field(parentName, parentType)); + return getDirectStateAccessorFor(targetRes, null); + } + } + + @Override + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes= target.getResource(); + if (from != null) { + ResourcePath fromRes= from.getResource(); + if (!target.isOutside()) { + return getDirectStateAccessorFor(targetRes, fromRes); + } + Term getter = null; + String targetComponentName = getComponentName(targetRes.getResourceHierarchy(), langSpec); + if (generatesComponent(targetRes.getResourceHierarchy())) { + getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(langSpec.toVariableName(targetComponentName), targetRes.getResourceStateType())); + } else { + String parentName = langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy().getParent(), langSpec)); + Type parentType = targetRes.getResourceHierarchy().getParent().getResourceStateType(); + getter = new Term(new Symbol(getterPrefix + targetComponentName, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(parentName, parentType)); + } + return getter; + } else { + return getDirectStateAccessorFor(targetRes, null); + } + } + + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { + if (fromRes != null) { + if (targetRes.equals(fromRes)) { + return new Field(fieldOfResourceState, + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + // for reference channel member + if (fromRes.isAncestorOf(targetRes)) { + Stack pathStack = new Stack<>(); + ResourcePath curPath = targetRes; + do { + pathStack.push(curPath); + curPath = curPath.getParent(); + } while (!curPath.equals(fromRes)); + // iterate from the fromRes resource + return getRelativePath(targetRes, pathStack); + } + if (generatesComponent(targetRes.getResourceHierarchy())) { + Term getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + getter.addChild(new Field(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), targetRes.getResourceStateType())); + return getter; + } else { + return new Field(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), targetRes.getResourceStateType()); + } + } else { + // (#3) access from the outside of the hierarchy (must be kept consistent with #4) + Stack pathStack = new Stack<>(); + ResourcePath curPath = targetRes; + do { + pathStack.push(curPath); + curPath = curPath.getParent(); + } while (curPath != null); + // iterate from the root resource + return getRelativePath(targetRes, pathStack); + } + } + + private Expression getRelativePath(ResourcePath targetRes, Stack pathStack) { + ResourcePath curPath; + Term getter = null; + int arity = 2; + boolean doesChainInvocations = true; + while (!pathStack.empty()) { + curPath = pathStack.pop(); + String typeName = getComponentName(curPath.getResourceHierarchy(), langSpec); + if (getter == null && generatesComponent(curPath.getResourceHierarchy())) { + // root resource + String fieldName = langSpec.toVariableName(typeName); + getter = new Field(fieldName, new Type(typeName, typeName)); + } else { + if (generatesComponent(curPath.getResourceHierarchy())) { + if (arity == 2) { + Term newGetter = new Term(new Symbol(getterPrefix + typeName, -1, Symbol.Type.METHOD)); + newGetter.addChild(getter); + if (curPath.getResourceHierarchy().getNumParameters() > 0) { + Expression param = curPath.getLastParam(); + if (param != null) { + newGetter.addChild(param); + newGetter.getSymbol().setArity(2); + } + } + getter = newGetter; + } else { + // add the last path parameter. + if (curPath.getResourceHierarchy().getNumParameters() > 0) { + Expression param = curPath.getLastParam(); + if (param != null) { + getter.getSymbol().setArity(arity); + getter.addChild(param); + } + } + } + arity = 2; + doesChainInvocations = true; + } else { + // to get a descendant resource directly. (e.g, .todos.{year}.{month}.{day}.{id} ==> .getTodos().getTodo(year, month, day, id)) + if (doesChainInvocations) { + Term newGetter = new Term(new Symbol(getterPrefix + typeName, -1, Symbol.Type.METHOD)); + newGetter.addChild(getter); + getter = newGetter; + doesChainInvocations = false; + } + if (curPath.getResourceHierarchy().getNumParameters() > 0) { + // may change the symbol name + getter.getSymbol().changeName(getterPrefix + typeName); + // add a path parameter. + Expression param = curPath.getLastParam(); + if (param != null) { + getter.getSymbol().setArity(arity); + getter.addChild(param); + arity++; + } + } + } + } + } + + if (generatesComponent(targetRes.getResourceHierarchy())) { + Term newGetter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + newGetter.addChild(getter); + getter = newGetter; } return getter; - } else { - return getDirectStateAccessorFor(targetRes, null); } - } + }; + } else { + return new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + if (from != null && !target.isOutside()) { + ResourcePath fromRes = from.getResource(); + if (targetRes.getCommonPrefix(fromRes) != null) { + return getDirectStateAccessorFor(targetRes, fromRes); + } + } + // for reference channel member + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } - @Override - public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes= target.getResource(); - if (from != null) { - ResourcePath fromRes= from.getResource(); - if (!target.isOutside()) { - return getDirectStateAccessorFor(targetRes, fromRes); + @Override + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + if (from != null && !target.isOutside()) { + ResourcePath fromRes = from.getResource(); + if (targetRes.getCommonPrefix(fromRes) != null) { + return getDirectStateAccessorFor(targetRes, fromRes); + } } - Term getter = null; - String targetComponentName = getComponentName(targetRes.getResourceHierarchy(), langSpec); - if (generatesComponent(targetRes.getResourceHierarchy())) { - getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); - getter.addChild(new Field(langSpec.toVariableName(targetComponentName), targetRes.getResourceStateType())); - } else { - String parentName = langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy().getParent(), langSpec)); - Type parentType = targetRes.getResourceHierarchy().getParent().getResourceStateType(); - getter = new Term(new Symbol(getterPrefix + targetComponentName, 1, Symbol.Type.METHOD)); - getter.addChild(new Field(parentName, parentType)); - } - return getter; - } else { - return getDirectStateAccessorFor(targetRes, null); + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); } - } - - @Override - public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { - if (fromRes != null) { + + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { + if (fromRes != null && !fromRes.getResourceHierarchy().isAncestorOf(targetRes.getResourceHierarchy())) { + if (targetRes.equals(fromRes)) { + return new Field(fieldOfResourceState, + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + // for reference channel member + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } else { + // (#3) access from an ancestor or outside of the hierarchy (must be kept consistent with #4) + Stack pathStack = new Stack<>(); + ResourcePath curPath = targetRes; + do { + if (fromRes != null && curPath.equals(fromRes)) break; + pathStack.push(curPath); + curPath = curPath.getParent(); + } while (curPath != null); + // iterate from the `from' resource + Term getter = null; + int arity = 2; + boolean doesChainInvocations = true; + while (!pathStack.empty()) { + curPath = pathStack.pop(); + String typeName = getComponentName(curPath.getResourceHierarchy(), langSpec); + if (getter == null && fromRes == null) { + // root resource + String fieldName = langSpec.toVariableName(typeName); + getter = new Field(fieldName, new Type(typeName, typeName)); + } else { + if (generatesComponent(curPath.getResourceHierarchy())) { + if (arity == 2) { + Term newGetter = new Term(new Symbol(getterPrefix + typeName, -1, Symbol.Type.METHOD)); + newGetter.addChild(getter); + if (curPath.getResourceHierarchy().getNumParameters() > 0) { + Expression param = curPath.getLastParam(); + if (param != null) { + newGetter.addChild(param); + newGetter.getSymbol().setArity(2); + } + } + getter = newGetter; + } else { + // add the last path parameter. + if (curPath.getResourceHierarchy().getNumParameters() > 0) { + Expression param = curPath.getLastParam(); + if (param != null) { + getter.getSymbol().setArity(arity); + getter.addChild(param); + } + } + } + arity = 2; + doesChainInvocations = true; + } else { + // to get a descendant resource directly. (e.g, .todos.{year}.{month}.{day}.{id} ==> .getTodos().getTodo(year, month, day, id)) + if (doesChainInvocations) { + Term newGetter = new Term(new Symbol(getterPrefix + typeName, -1, Symbol.Type.METHOD)); + newGetter.addChild(getter); + getter = newGetter; + doesChainInvocations = false; + } + if (curPath.getResourceHierarchy().getNumParameters() > 0) { + // may change the symbol name + getter.getSymbol().changeName(getterPrefix + typeName); + // add a path parameter. + Expression param = curPath.getLastParam(); + if (param != null) { + getter.getSymbol().setArity(arity); + getter.addChild(param); + arity++; + } + } + } + } + } + + if (generatesComponent(targetRes.getResourceHierarchy())) { + Term newGetter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + newGetter.addChild(getter); + getter = newGetter; + } + return getter; + } + } + }; + } + } + + protected IResourceStateAccessor getRefAccessor(IPlatformSpecific platformSpec) { + if (platformSpec.isMonolithic()) { + return new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes= target.getResource(); + ResourcePath fromRes= from.getResource(); + if (targetRes.equals(fromRes)) { + return new Field(fieldOfResourceState, + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + // use the cached value as the current state + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + + @Override + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes= target.getResource(); + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { + if (fromRes != null && targetRes.equals(fromRes)) { + return new Field(fieldOfResourceState, + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + // for reference channel member + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + }; + } else { + return new IResourceStateAccessor() { + @Override + public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + ResourcePath fromRes = from.getResource(); if (targetRes.equals(fromRes)) { return new Field(fieldOfResourceState, targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } // for reference channel member - if (fromRes.isAncestorOf(targetRes)) { - Stack pathStack = new Stack<>(); - ResourcePath curPath = targetRes; - do { - pathStack.push(curPath); - curPath = curPath.getParent(); - } while (!curPath.equals(fromRes)); - // iterate from the fromRes resource - return getRelativePath(targetRes, pathStack); - } - if (generatesComponent(targetRes.getResourceHierarchy())) { - Term getter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); - getter.addChild(new Field(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), targetRes.getResourceStateType())); - return getter; - } else { - return new Field(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), targetRes.getResourceStateType()); - } - } else { - // (#3) access from the outside of the hierarchy (must be kept consistent with #4) - Stack pathStack = new Stack<>(); - ResourcePath curPath = targetRes; - do { - pathStack.push(curPath); - curPath = curPath.getParent(); - } while (curPath != null); - // iterate from the root resource - return getRelativePath(targetRes, pathStack); - } - } - - private Expression getRelativePath(ResourcePath targetRes, Stack pathStack) { - ResourcePath curPath; - Term getter = null; - int arity = 2; - boolean doesChainInvocations = true; - while (!pathStack.empty()) { - curPath = pathStack.pop(); - String typeName = getComponentName(curPath.getResourceHierarchy(), langSpec); - if (getter == null && generatesComponent(curPath.getResourceHierarchy())) { - // root resource - String fieldName = langSpec.toVariableName(typeName); - getter = new Field(fieldName, new Type(typeName, typeName)); - } else { - if (generatesComponent(curPath.getResourceHierarchy())) { - if (arity == 2) { - Term newGetter = new Term(new Symbol(getterPrefix + typeName, -1, Symbol.Type.METHOD)); - newGetter.addChild(getter); - if (curPath.getResourceHierarchy().getNumParameters() > 0) { - Expression param = curPath.getLastParam(); - if (param != null) { - newGetter.addChild(param); - newGetter.getSymbol().setArity(2); - } - } - getter = newGetter; - } else { - // add the last path parameter. - if (curPath.getResourceHierarchy().getNumParameters() > 0) { - Expression param = curPath.getLastParam(); - if (param != null) { - getter.getSymbol().setArity(arity); - getter.addChild(param); - } - } - } - arity = 2; - doesChainInvocations = true; - } else { - // to get a descendant resource directly. (e.g, .todos.{year}.{month}.{day}.{id} ==> .getTodos().getTodo(year, month, day, id)) - if (doesChainInvocations) { - Term newGetter = new Term(new Symbol(getterPrefix + typeName, -1, Symbol.Type.METHOD)); - newGetter.addChild(getter); - getter = newGetter; - doesChainInvocations = false; - } - if (curPath.getResourceHierarchy().getNumParameters() > 0) { - // may change the symbol name - getter.getSymbol().changeName("get" + typeName); - // add a path parameter. - Expression param = curPath.getLastParam(); - if (param != null) { - getter.getSymbol().setArity(arity); - getter.addChild(param); - arity++; - } - } - } - } - } - - if (generatesComponent(targetRes.getResourceHierarchy())) { - Term newGetter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); - newGetter.addChild(getter); - getter = newGetter; - } - return getter; - } - }; - } - - protected IResourceStateAccessor getRefAccessor() { - return new IResourceStateAccessor() { - @Override - public Expression getCurrentStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes= target.getResource(); - ResourcePath fromRes= from.getResource(); - if (targetRes.equals(fromRes)) { - return new Field(fieldOfResourceState, + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } - // use the cached value as the current state - return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - @Override - public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { - ResourcePath targetRes= target.getResource(); - return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - - @Override - public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { - if (fromRes != null && targetRes.equals(fromRes)) { - return new Field(fieldOfResourceState, + @Override + public Expression getNextStateAccessorFor(ChannelMember target, ChannelMember from) { + ResourcePath targetRes = target.getResource(); + return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); } - // for reference channel member - return new Parameter(langSpec.toVariableName(getComponentName(targetRes.getResourceHierarchy(), langSpec)), - targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() - : DataConstraintModel.typeInt); - } - }; + + @Override + public Expression getDirectStateAccessorFor(ResourcePath targetRes, ResourcePath fromRes) { + if (fromRes != null && targetRes.equals(fromRes)) { + return new Field(fieldOfResourceState, + targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() + : DataConstraintModel.typeInt); + } + return null; + } + }; + } } } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java index 2e7a2fc..365a1c2 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/CodeGeneratorFromDataFlowGraph.java @@ -9,15 +9,17 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; + +import algorithms.TypeInference; + import java.util.Set; import java.util.Stack; -import java.util.AbstractMap.SimpleEntry; import code.ast.Annotation; import code.ast.Block; +import code.ast.CodeUtil; import code.ast.CompilationUnit; import code.ast.FieldDeclaration; -import code.ast.ImportDeclaration; import code.ast.MethodDeclaration; import code.ast.TypeDeclaration; import code.ast.VariableDeclaration; @@ -30,6 +32,7 @@ import models.algebra.Parameter; import models.algebra.ParameterizedIdentifierIsFutureWork; import models.algebra.Position; +import models.algebra.Symbol; import models.algebra.Term; import models.algebra.Type; import models.algebra.UnificationFailed; @@ -61,7 +64,7 @@ Map> dependedRootComponentGraph, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { Map resourceComponents = new HashMap<>(); Map resourceConstructors = new HashMap<>(); - List> constructorParams = new ArrayList<>(); + Map> constructorParams = new HashMap<>(); List> constructorStatements = new ArrayList<>(); Map>> updateStatements = new HashMap<>(); Map> descendantGetters = new HashMap<>(); @@ -92,15 +95,15 @@ if (component == null) { // Add compilation unit for this component. component = langSpec.newTypeDeclaration(resourceName); - if (platformSpec.hasComponentAnnotation() && resourceNode.getResourceHierarchy().getParent() == null) { + if (!platformSpec.isMonolithic() && resourceNode.getResourceHierarchy().getParent() == null) { // For each root node, add component annotations. - platformSpec.addComponentAnnotations(component, resourceNode.getResourceName()); + ((RestApiSpecific) platformSpec).addComponentAnnotations(component, resourceNode.getResourceName()); } resourceComponents.put(resourceNode.getResourceHierarchy(), component); CompilationUnit cu = langSpec.newCompilationUnit(component); - if (platformSpec.hasPlatformSpecificImports() && resourceNode.getResourceHierarchy().getParent() == null) { + if (!platformSpec.isMonolithic() && resourceNode.getResourceHierarchy().getParent() == null) { // For each root node, add platform specific imports. - platformSpec.addPlatformSpecificImports(cu); + ((RestApiSpecific) platformSpec).addPlatformSpecificImports(cu); } codes.add(cu); @@ -132,10 +135,12 @@ } // Declare the getter method in this resource to obtain the state. - MethodDeclaration stateGetter = declareStateGetterMethod(resourceNode, component, resStateType, langSpec); + MethodDeclaration stateGetter = declareStateGetterMethod(resourceNode, component, resStateType, platformSpec, langSpec); // Declare the accessor method in the main component to call the getter method. - declareAccessorInMainComponent(mainComponent, resourceNode, stateGetter, langSpec); + if (platformSpec.hasMain()) { + declareAccessorInMainComponent(mainComponent, resourceNode, stateGetter, platformSpec, langSpec); + } } if (component != null) { // (#1) Declare the getter methods in this resource to obtain the descendant resources. (complementary to #2) @@ -145,21 +150,26 @@ } // For each components (2nd pass). + Map priorMemberForInputChannel = new HashMap<>(); + Set generatedResources = new HashSet<>(); for (Node componentNode: components) { // Declare this resource. ResourceNode resourceNode = (ResourceNode) componentNode; Type resStateType = getImplStateType(resourceNode.getResourceHierarchy(), langSpec); TypeDeclaration component = null; TypeDeclaration parentComponent = null; + TypeDeclaration rootComponent = null; if (generatesComponent(resourceNode.getResourceHierarchy())) { component = resourceComponents.get(resourceNode.getResourceHierarchy()); } if (resourceNode.getResourceHierarchy().getParent() != null) { parentComponent = resourceComponents.get(resourceNode.getResourceHierarchy().getParent()); } + rootComponent = resourceComponents.get(resourceNode.getResourceHierarchy().getRoot()); - // Declare cache fields and update methods in this resource. - Map.Entry, Map>>> initStatementsAndUpdateUpdates = declareCacheFieldsAndUpdateMethods(resourceNode, component, parentComponent, langSpec); + // Declare cache fields and update methods in this resource, and an update accessor method in the type of root resource. + Map.Entry, Map>>> initStatementsAndUpdateUpdates + = declareCacheFieldsAndUpdateMethods(resourceNode, component, parentComponent, rootComponent, platformSpec, langSpec); if (component == null) { // Constructor statements were not added to any component because no component had been generated. for (String statement: initStatementsAndUpdateUpdates.getKey()) { @@ -170,30 +180,40 @@ updateStatements.put(entry.getKey(), entry.getValue()); } - // Declare the fields to refer to other resources in the parent/this component, and the state field in the parent component. - declareFieldsToReferToOtherResourcesAndStateFieldInParentComponent(resourceNode, component, parentComponent, constructorParams, langSpec); + // Declare the fields to refer to other resources for push/pull transfer in the parent/this component, and the state field in the parent component. + declareFieldsToReferToOtherResourcesAndStateFieldInParentComponent(resourceNode, component, parentComponent, constructorParams, platformSpec, langSpec); // (#2) Declare the getter method to obtain the resource state in an ancestor resource. (complementary to #1) if (component == null) { - MethodDeclaration stateGetter = declareStateGetterMethodInAncestor(resourceNode, resourceComponents, resStateType, langSpec); + MethodDeclaration stateGetter = declareStateGetterMethodInAncestor(resourceNode, resourceComponents, resStateType, platformSpec, langSpec); - if (stateGetter != null) { + if (stateGetter != null && platformSpec.hasMain()) { // Declare the accessor method in the main component to call the getter method. - declareAccessorInMainComponent(mainComponent, resourceNode, stateGetter, langSpec); + declareAccessorInMainComponent(mainComponent, resourceNode, stateGetter, platformSpec, langSpec); } } + if (!platformSpec.isMonolithic()) { + // Declare the getter accessor in the root resource. + declareGetterAccessorInTheRootResource(resourceNode, rootComponent, platformSpec, langSpec); + } + // Declare input methods in this component and the main component. - Map.Entry, Map>>> initStatementsAndInputUpdates = declareInputMethodsInThisAndMainComponents(resourceNode, component, parentComponent, mainComponent, model, langSpec); - if (component == null) { - // Constructor statements were not added to any component because no component had been generated. - for (String statement: initStatementsAndInputUpdates.getKey()) { - constructorStatements.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy().getParent(), statement)); + if (!generatedResources.contains(resourceNode.getResourceHierarchy())) { + Map.Entry, Map>>> initStatementsAndInputUpdates + = declareInputMethodsInThisAndMainComponents(resourceNode, component, parentComponent, mainComponent, rootComponent, model, priorMemberForInputChannel, platformSpec, langSpec); + if (component == null) { + // Constructor statements were not added to any component because no component had been generated. + for (String statement: initStatementsAndInputUpdates.getKey()) { + constructorStatements.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy().getParent(), statement)); + } + } + for (Map.Entry>> entry: initStatementsAndInputUpdates.getValue().entrySet()) { + updateStatements.put(entry.getKey(), entry.getValue()); } } - for (Map.Entry>> entry: initStatementsAndInputUpdates.getValue().entrySet()) { - updateStatements.put(entry.getKey(), entry.getValue()); - } + + generatedResources.add(resourceNode.getResourceHierarchy()); } // Add constructor parameters to the ancestor components. @@ -217,14 +237,14 @@ } private static List addConstructorParameters(ResourceHierarchy resource, Map resourceComponents, - Map resourceConstructors, List> constructorParams, ILanguageSpecific langSpec) { + Map resourceConstructors, Map> constructorParams, ILanguageSpecific langSpec) { List params = new ArrayList<>(); for (ResourceHierarchy child: resource.getChildren()) { params.addAll(addConstructorParameters(child, resourceComponents, resourceConstructors, constructorParams, langSpec)); } - for (Entry paramEnt: constructorParams) { - if (paramEnt.getKey().equals(resource)) { - params.add(paramEnt.getValue()); + if (constructorParams.get(resource) != null) { + for (VariableDeclaration param: constructorParams.get(resource).values()) { + params.add(param); } } if (params.size() > 0) { @@ -262,6 +282,7 @@ } private void addUpdateStatementWithConstructorInvocationToMethod(MethodDeclaration method, Expression exp, ResourceHierarchy resource, ResourceHierarchy descendantRes, TypeDeclaration descendantComponent, ILanguageSpecific langSpec) { + // Replace each json term in exp with the corresponding constructor invocation. Type replacedJsonType = descendantRes.getResourceStateType(); String replacingClassName = getComponentName(descendantRes, langSpec); Type descendantType = new Type(replacingClassName, replacingClassName); @@ -277,10 +298,11 @@ List params = new ArrayList<>(); if (childConstructor != null) { for (VariableDeclaration var: childConstructor.getParameters()) { + // Extract the argument of each constructor parameter from jsonTerm. JsonAccessor jsonMember = new JsonAccessor(DataConstraintModel.dot); jsonMember.addChild(jsonTerm); jsonMember.addChild(new Constant(var.getName(), DataConstraintModel.typeString)); - Expression param = jsonMember.reduce(); + Expression param = jsonMember.reduce(); // Reduce {"name": "foo", age: 25}.name => "foo" if (param != null) { if (param instanceof Term) { if (((Term) param).getType() == null) { @@ -439,12 +461,22 @@ return constructor; } - private void declareStateField(ResourceNode resourceNode, String resourceName, TypeDeclaration component, Type resStateType, List> constructorParams, ILanguageSpecific langSpec) { + private void declareStateField(ResourceNode resourceNode, String resourceName, TypeDeclaration component, Type resStateType, Map> constructorParams, ILanguageSpecific langSpec) { Set children = resourceNode.getResourceHierarchy().getChildren(); if (children == null || children.size() == 0) { // leaf resource. FieldDeclaration stateField = langSpec.newFieldDeclaration(resStateType, fieldOfResourceState, langSpec.getFieldInitializer(resStateType, resourceNode.getResourceHierarchy().getInitialValue())); component.addField(stateField); + // Add a parameter to initialize the state field to the constructor. +// Map nameToParam = constructorParams.get(resourceNode.getResourceHierarchy()); +// if (nameToParam == null) { +// nameToParam = new HashMap<>(); +// constructorParams.put(resourceNode.getResourceHierarchy(), nameToParam); +// } +// String varName = fieldOfResourceState; +// if (nameToParam.get(varName) == null) { +// nameToParam.put(varName, langSpec.newVariableDeclaration(resStateType, varName)); +// } } else { ResourceHierarchy child = children.iterator().next(); if (children.size() == 1 && child.getNumParameters() > 0) { @@ -468,7 +500,8 @@ } } - private void declareFieldsToReferToOtherResourcesAndStateFieldInParentComponent(ResourceNode resourceNode, TypeDeclaration component, TypeDeclaration parentComponent, List> constructorParams, ILanguageSpecific langSpec) { + private void declareFieldsToReferToOtherResourcesAndStateFieldInParentComponent(ResourceNode resourceNode, TypeDeclaration component, TypeDeclaration parentComponent, + Map> constructorParams, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { // Declare reference fields for push data transfer. boolean noPullTransfer = true; for (Edge resToCh : resourceNode.getOutEdges()) { @@ -501,12 +534,17 @@ DataTransferChannel ch = chNode.getChannel(); // Check if the destination resource is outside of the channel scope. boolean outsideOutputResource = false; + ChannelMember out = null; for (ChannelMember cm: ch.getOutputChannelMembers()) { - if (((ResourceNode) chToRes.getDestination()).getInSideResources().contains(cm.getResource()) && cm.isOutside()) { - outsideOutputResource = true; // Regarded as push transfer. - break; + if (((ResourceNode) chToRes.getDestination()).getInSideResources().contains(cm.getResource())) { + out = cm; + if (cm.isOutside()) { + outsideOutputResource = true; // Regarded as push transfer. + break; + } } } + ResourcePath dstResPath = out.getResource(); // Also take into account the channel hierarchy to determine push/pull transfer. if (descendantDstChannels.contains(chNode)) { outsideOutputResource = true; // Regarded as (broadcasting) push transfer. @@ -515,64 +553,103 @@ outsideInputResource = true; // Regarded as (collecting) pull transfer. } if ((((PushPullAttribute) re.getAttribute()).getSelectedOption() == PushPullValue.PUSH && !outsideInputResource) || outsideOutputResource) { - // Declare a field in the parent component to refer to the destination resource of push transfer. + // Declare a field in the parent or this component to refer to the destination resource of push transfer. if (!generatesComponent(dstRes)) { dstRes = dstRes.getParent(); } String dstResName = getComponentName(dstRes, langSpec); FieldDeclaration refFieldForPush = langSpec.newFieldDeclaration(new Type(dstResName, dstResName), langSpec.toVariableName(dstResName)); VariableDeclaration refVarForPush = langSpec.newVariableDeclaration(new Type(dstResName, dstResName), langSpec.toVariableName(dstResName)); - if (component != null) { - // A component is created for this resource. - if (resourceNode.getResourceHierarchy() != dstRes) { - component.addField(refFieldForPush); - if (!outsideOutputResource) { - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), refVarForPush)); - } + if (!platformSpec.isMonolithic() + && (outsideOutputResource || (resourceNode.getOutSideResource(ch).getCommonPrefix(dstResPath) == null && platformSpec.isDifferentTreesAsDifferentServices()))) { + // Inter-service (for REST API) + if (parentComponent != null && + !((RestApiSpecific) platformSpec).hasHttpClientFieldDeclaration(parentComponent)) { + // Declare a client field to connect to the destination resource of push transfer. + ((RestApiSpecific) platformSpec).addHttpClientFieldDeclaration(parentComponent); } } else { - // No component is created for this resource. - if (resourceNode.getParent().getResourceHierarchy() != dstRes) { - parentComponent.addField(refFieldForPush); - if (!outsideOutputResource) { - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refVarForPush)); + // Monolithic or Inner-service + if (component != null) { + // A component is created for this resource. + if (resourceNode.getResourceHierarchy() != dstRes) { + component.addField(refFieldForPush); + if (!outsideOutputResource) { + Map nameToParam = constructorParams.get(resourceNode.getResourceHierarchy()); + if (nameToParam == null) { + nameToParam = new HashMap<>(); + constructorParams.put(resourceNode.getResourceHierarchy(), nameToParam); + } + if (nameToParam.get(dstResName) == null) { + nameToParam.put(dstResName, refVarForPush); + } + } + } + } else { + // No component is created for this resource. + if (resourceNode.getParent().getResourceHierarchy() != dstRes && parentComponent != null) { + parentComponent.addField(refFieldForPush); + if (!outsideOutputResource) { + Map nameToParam = constructorParams.get(resourceNode.getParent().getResourceHierarchy()); + if (nameToParam == null) { + nameToParam = new HashMap<>(); + constructorParams.put(resourceNode.getParent().getResourceHierarchy(), nameToParam); + } + if (nameToParam.get(dstResName) == null) { + nameToParam.put(dstResName, refVarForPush); + } + } } } - } - if (outsideOutputResource) { - // When the reference to the destination resource can vary. - if (dstRes.getParent() != null) { - // Reference to its root resource. - String dstRootResName = getComponentName(dstRes.getRoot(), langSpec); - Type dstRootResType = new Type(dstRootResName, dstRootResName); - dstRootResName = langSpec.toVariableName(dstRootResName); - FieldDeclaration refRootFieldForPush = langSpec.newFieldDeclaration(dstRootResType, dstRootResName); - VariableDeclaration refRootVarForPush = langSpec.newVariableDeclaration(dstRootResType, dstRootResName); - if (component != null) { - // A component is created for this resource. - boolean existsField = false; - for (FieldDeclaration field: component.getFields()) { - if (dstRootResName.equals(field.getName())) { - existsField = true; - break; + if (outsideOutputResource) { + // When the reference to the destination resource can vary. + if (dstRes.getParent() != null) { + // Reference to its root resource. + String dstRootResName = getComponentName(dstRes.getRoot(), langSpec); + Type dstRootResType = new Type(dstRootResName, dstRootResName); + dstRootResName = langSpec.toVariableName(dstRootResName); + FieldDeclaration refRootFieldForPush = langSpec.newFieldDeclaration(dstRootResType, dstRootResName); + VariableDeclaration refRootVarForPush = langSpec.newVariableDeclaration(dstRootResType, dstRootResName); + if (component != null) { + // A component is created for this resource. + boolean existsField = false; + for (FieldDeclaration field: component.getFields()) { + if (dstRootResName.equals(field.getName())) { + existsField = true; + break; + } } - } - if (!existsField) { - component.addField(refRootFieldForPush); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), refRootVarForPush)); - } - } else { - // No component is created for this resource. - boolean existsField = false; - for (FieldDeclaration field: parentComponent.getFields()) { - if (dstRootResName.equals(field.getName())) { - existsField = true; - break; + if (!existsField) { + component.addField(refRootFieldForPush); + Map nameToParam = constructorParams.get(resourceNode.getResourceHierarchy()); + if (nameToParam == null) { + nameToParam = new HashMap<>(); + constructorParams.put(resourceNode.getResourceHierarchy(), nameToParam); + } + if (nameToParam.get(dstRootResName) == null) { + nameToParam.put(dstRootResName, refRootVarForPush); + } } - } - if (!existsField) { - parentComponent.addField(refRootFieldForPush); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refRootVarForPush)); + } else { + // No component is created for this resource. + boolean existsField = false; + for (FieldDeclaration field: parentComponent.getFields()) { + if (dstRootResName.equals(field.getName())) { + existsField = true; + break; + } + } + if (!existsField) { + parentComponent.addField(refRootFieldForPush); + Map nameToParam = constructorParams.get(resourceNode.getParent().getResourceHierarchy()); + if (nameToParam == null) { + nameToParam = new HashMap<>(); + constructorParams.put(resourceNode.getParent().getResourceHierarchy(), nameToParam); + } + if (nameToParam.get(dstRootResName) == null) { + nameToParam.put(dstRootResName, refRootVarForPush); + } + } } } } @@ -583,9 +660,23 @@ } // Declare reference fields for pull data transfer. for (Edge chToRes : resourceNode.getInEdges()) { - for (Edge resToCh: chToRes.getSource().getInEdges()) { + ChannelNode directSrcChNode = (ChannelNode) chToRes.getSource(); + DataTransferChannel directSrcCh = directSrcChNode.getChannel(); + // Should take into account the channel hierarchy. + Set ancestorSrcChannels = directSrcChNode.getAncestors(); + Set descendantSrcChannels = directSrcChNode.getDescendants(); + Set inEdges = new HashSet<>(); + inEdges.addAll(directSrcChNode.getInEdges()); + for (ChannelNode ancestorSrc: ancestorSrcChannels) { + inEdges.addAll(ancestorSrc.getInEdges()); + } + for (ChannelNode descendantSrc: descendantSrcChannels) { + inEdges.addAll(descendantSrc.getInEdges()); + } + for (Edge resToCh: inEdges) { DataFlowEdge re = (DataFlowEdge) resToCh; - DataTransferChannel ch = ((ChannelNode) re.getDestination()).getChannel(); + ChannelNode chNode = (ChannelNode) re.getDestination(); + DataTransferChannel ch = chNode.getChannel(); ResourcePath srcRes = ((ResourceNode) re.getSource()).getOutSideResource(ch); // Check if the source resource is outside of the channel scope. boolean outsideInputResource = false; @@ -603,6 +694,13 @@ break; } } + // Also take into account the channel hierarchy to determine push/pull transfer. + if (descendantSrcChannels.contains(chNode)) { + outsideInputResource = true; // Regarded as (collecting) pull transfer. + } + if (ancestorSrcChannels.contains(chNode)) { + outsideOutputResource = true; // Regarded as (broadcasting) push transfer. + } if ((((PushPullAttribute) re.getAttribute()).getSelectedOption() != PushPullValue.PUSH && !outsideOutputResource) || outsideInputResource) { noPullTransfer = false; // Declare a field in the parent/this component to refer to the source resource of pull transfer. @@ -612,57 +710,97 @@ String srcResName = getComponentName(srcRes.getResourceHierarchy(), langSpec); FieldDeclaration refFieldForPull = langSpec.newFieldDeclaration(new Type(srcResName, srcResName), langSpec.toVariableName(srcResName)); VariableDeclaration refVarForPull = langSpec.newVariableDeclaration(new Type(srcResName, srcResName), langSpec.toVariableName(srcResName)); - if (component != null) { - // A component is created for this resource. - if (resourceNode.getResourceHierarchy() != srcRes.getResourceHierarchy()) { - component.addField(refFieldForPull); - if (!outsideInputResource) { - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), refVarForPull)); - } + if (!platformSpec.isMonolithic() + && (outsideInputResource || (resourceNode.getInSideResource(ch).getCommonPrefix(srcRes) == null && platformSpec.isDifferentTreesAsDifferentServices()))) { + // Inter-service (for REST API) + if (parentComponent != null + && !((RestApiSpecific) platformSpec).hasHttpClientFieldDeclaration(parentComponent)) { + // Declare a client field to connect to the destination resource of push transfer. + ((RestApiSpecific) platformSpec).addHttpClientFieldDeclaration(parentComponent); } } else { - // No component is created for this resource. - if (resourceNode.getParent().getResourceHierarchy() != srcRes.getResourceHierarchy()) { - parentComponent.addField(refFieldForPull); - if (!outsideInputResource) { - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refVarForPull)); + // Monolithic or Inner-service (for REST API) + // Declare a field to directly refer to the source resource of pull transfer. + if (component != null) { + // A component is created for this resource. + if (resourceNode.getResourceHierarchy() != srcRes.getResourceHierarchy()) { + component.addField(refFieldForPull); + if (!outsideInputResource) { + Map nameToParam = constructorParams.get(resourceNode.getResourceHierarchy()); + if (nameToParam == null) { + nameToParam = new HashMap<>(); + constructorParams.put(resourceNode.getResourceHierarchy(), nameToParam); + } + if (nameToParam.get(srcResName) == null) { + nameToParam.put(srcResName, refVarForPull); + } + } + } + } else { + // No component is created for this resource. + if (resourceNode.getParent().getResourceHierarchy() != srcRes.getResourceHierarchy() && parentComponent != null) { + parentComponent.addField(refFieldForPull); + if (!outsideInputResource) { + Map nameToParam = constructorParams.get(resourceNode.getParent().getResourceHierarchy()); + if (nameToParam == null) { + nameToParam = new HashMap<>(); + constructorParams.put(resourceNode.getParent().getResourceHierarchy(), nameToParam); + } + if (nameToParam.get(srcResName) == null) { + nameToParam.put(srcResName, refVarForPull); + } + } } } - } - if (outsideInputResource) { - // When the reference to the source resource can vary. - if (srcRes.getParent() != null) { - // Reference to its root resource. - String srcRootResName = getComponentName(srcRes.getRoot().getResourceHierarchy(), langSpec); - Type srcRootResType = new Type(srcRootResName, srcRootResName); - srcRootResName = langSpec.toVariableName(srcRootResName); - FieldDeclaration refRootFieldForPull = langSpec.newFieldDeclaration(srcRootResType, srcRootResName); - VariableDeclaration refRootVarForPull = langSpec.newVariableDeclaration(srcRootResType, srcRootResName); - if (component != null) { - // A component is created for this resource. - boolean existsField = false; - for (FieldDeclaration field: component.getFields()) { - if (srcRootResName.equals(field.getName())) { - existsField = true; - break; + if (outsideInputResource) { + // When the reference to the source resource can vary. + if (srcRes.getParent() != null) { + // Reference to its root resource. + String srcRootResName = getComponentName(srcRes.getRoot().getResourceHierarchy(), langSpec); + Type srcRootResType = new Type(srcRootResName, srcRootResName); + srcRootResName = langSpec.toVariableName(srcRootResName); + FieldDeclaration refRootFieldForPull = langSpec.newFieldDeclaration(srcRootResType, srcRootResName); + VariableDeclaration refRootVarForPull = langSpec.newVariableDeclaration(srcRootResType, srcRootResName); + if (component != null) { + // A component is created for this resource. + boolean existsField = false; + for (FieldDeclaration field: component.getFields()) { + if (srcRootResName.equals(field.getName())) { + existsField = true; + break; + } } - } - if (!existsField) { - component.addField(refRootFieldForPull); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), refRootVarForPull)); - } - } else { - // No component is created for this resource. - boolean existsField = false; - for (FieldDeclaration field: parentComponent.getFields()) { - if (srcRootResName.equals(field.getName())) { - existsField = true; - break; + if (!existsField) { + component.addField(refRootFieldForPull); + Map nameToParam = constructorParams.get(resourceNode.getResourceHierarchy()); + if (nameToParam == null) { + nameToParam = new HashMap<>(); + constructorParams.put(resourceNode.getResourceHierarchy(), nameToParam); + } + if (nameToParam.get(srcRootResName) == null) { + nameToParam.put(srcRootResName, refRootVarForPull); + } } - } - if (!existsField) { - parentComponent.addField(refRootFieldForPull); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), refRootVarForPull)); + } else { + // No component is created for this resource. + boolean existsField = false; + for (FieldDeclaration field: parentComponent.getFields()) { + if (srcRootResName.equals(field.getName())) { + existsField = true; + break; + } + } + if (!existsField) { + parentComponent.addField(refRootFieldForPull); + Map nameToParam = constructorParams.get(resourceNode.getParent().getResourceHierarchy()); + if (nameToParam == null) { + nameToParam = new HashMap<>(); + constructorParams.put(resourceNode.getParent().getResourceHierarchy(), nameToParam); + } + if (nameToParam.get(srcRootResName) == null) { + nameToParam.put(srcRootResName, refRootVarForPull); + } + } } } } @@ -685,30 +823,48 @@ if (!existsField) { FieldDeclaration stateField = langSpec.newFieldDeclaration(res.getResourceStateType(), resName); parentComponent.addField(stateField); - constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getParent().getResourceHierarchy(), langSpec.newVariableDeclaration(res.getResourceStateType(), resName))); + Map nameToParam = constructorParams.get(resourceNode.getParent().getResourceHierarchy()); + if (nameToParam == null) { + nameToParam = new HashMap<>(); + constructorParams.put(resourceNode.getParent().getResourceHierarchy(), nameToParam); + } + if (nameToParam.get(resName) == null) { + nameToParam.put(resName, langSpec.newVariableDeclaration(res.getResourceStateType(), resName)); + } } } } } - private MethodDeclaration declareStateGetterMethod(ResourceNode resourceNode, TypeDeclaration component, Type resStateType, ILanguageSpecific langSpec) { + private MethodDeclaration declareStateGetterMethod(ResourceNode resourceNode, TypeDeclaration component, Type resStateType, + IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { // Declare the getter method of the resource state. MethodDeclaration stateGetter = langSpec.newMethodDeclaration(getterOfResourceState, resStateType); + if (!platformSpec.isMonolithic() && resourceNode.getResourceHierarchy().getParent() == null) { + // Since this getter is also an accessor. + ((RestApiSpecific) platformSpec).addGetAnnotations(stateGetter); + } component.addMethod(stateGetter); boolean hasDescendantIn = hasDescendantInput(resourceNode); if (((StoreAttribute) resourceNode.getAttribute()).isStored() && !hasDescendantIn) { - fillStateGetterMethod(stateGetter, resourceNode.getResourceHierarchy(), resStateType, langSpec); + fillStateGetterMethod(stateGetter, resourceNode.getResourceHierarchy(), resStateType, platformSpec, langSpec); } else { // invocations to other getter methods when at least one incoming data-flow edges is PULL-style. - addOtherGetterInvocationsToStateGatter(stateGetter, resourceNode, langSpec); + if (addOtherGetterInvocationsToStateGatter(stateGetter, resourceNode, platformSpec, langSpec)) { + // Declare a client field to connect to the destination resource of push transfer. + if (!((RestApiSpecific) platformSpec).hasHttpClientFieldDeclaration(component)) { + ((RestApiSpecific) platformSpec).addHttpClientFieldDeclaration(component); + } + } } return stateGetter; } - private MethodDeclaration declareStateGetterMethodInAncestor(ResourceNode resourceNode, Map resourceComponents, Type resStateType, ILanguageSpecific langSpec) { + private MethodDeclaration declareStateGetterMethodInAncestor(ResourceNode resourceNode, Map resourceComponents, Type resStateType, + IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { // Search an ancestor in which the getter method is declared. ResourceNode ancestorNode = resourceNode; ResourceNode childNode = null; @@ -755,7 +911,12 @@ if (((StoreAttribute) resourceNode.getAttribute()).isStored() && !hasDescendantIn) { fillDescendantGetterMethod(stateGetter, resourceNode.getResourceHierarchy(), childNode.getResourceHierarchy(), ancestorNode.getResourceHierarchy(), ancestorComponent, langSpec); } else { - addOtherGetterInvocationsToStateGatter(stateGetter, resourceNode, langSpec); + if (addOtherGetterInvocationsToStateGatter(stateGetter, resourceNode, platformSpec, langSpec)) { + // Declare a client field to connect to the destination resource of push transfer. + if (ancestorComponent != null && !((RestApiSpecific) platformSpec).hasHttpClientFieldDeclaration(ancestorComponent)) { + ((RestApiSpecific) platformSpec).addHttpClientFieldDeclaration(ancestorComponent); + } + } } return stateGetter; @@ -776,8 +937,9 @@ return hasDescendantIn; } - private void addOtherGetterInvocationsToStateGatter(MethodDeclaration stateGetter, ResourceNode resourceNode, - ILanguageSpecific langSpec) { + private boolean addOtherGetterInvocationsToStateGatter(MethodDeclaration stateGetter, ResourceNode resourceNode, + IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + boolean bDeclareClientField = false; try { // Data transfer on the same channel hierarchy. boolean isContainedPush = false; @@ -798,11 +960,29 @@ if (((PushPullAttribute) dIn.getAttribute()).getSelectedOption() == PushPullValue.PUSH) { // PUSH transfer isContainedPush = true; - inputResourceToStateAccessor.put(in, getPushAccessor()); + inputResourceToStateAccessor.put(in, getPushAccessor(platformSpec)); } else { // PULL transfer - inputResourceToStateAccessor.put(in, getPullAccessor()); + inputResourceToStateAccessor.put(in, getPullAccessor(platformSpec)); ch = ((ChannelNode) resToCh.getDestination()).getChannel(); // pull containing input side channel is at most one. + if (!platformSpec.isMonolithic() + && !in.isOutside() + && in.getResource().getCommonPrefix(resourceNode.getInSideResource(ch2)) == null + && platformSpec.isDifferentTreesAsDifferentServices()) { + // for REST API + ResourcePath srcResPath = in.getResource(); + String srcResourceName = langSpec.toVariableName(getComponentName(srcResPath.getResourceHierarchy(), langSpec)); + Type srcResourceType = srcResPath.getResourceStateType(); + List pathParams = new ArrayList<>(); + for (Expression pathExp: srcResPath.getPathParams()) { + String[] sideEffects = new String[] {""}; + pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); + } + generatePullDataTransfer(stateGetter, srcResourceName, + srcResPath.getResourceHierarchy().toResourcePath(pathParams), srcResourceType, + true, platformSpec, langSpec); + bDeclareClientField = true; + } } } } @@ -818,21 +998,64 @@ } // for reference channel members. - for (ChannelMember c: ch.getReferenceChannelMembers()) { - inputResourceToStateAccessor.put(c, getPullAccessor()); // by pull data transfer + ResourcePath dstResPath = resourceNode.getInSideResource(ch); + for (ChannelMember rc: ch.getReferenceChannelMembers()) { + inputResourceToStateAccessor.put(rc, getPullAccessor(platformSpec)); // by pull data transfer + ResourcePath refResPath = rc.getResource(); + if (!platformSpec.isMonolithic() + && (rc.isOutside() + || (refResPath.getCommonPrefix(dstResPath) == null && platformSpec.isDifferentTreesAsDifferentServices()))) { + // for REST API + String refResourceName = langSpec.toVariableName(getComponentName(refResPath.getResourceHierarchy(), langSpec)); + Type refResourceType = refResPath.getResourceStateType(); + List pathParams = new ArrayList<>(); + for (Expression pathExp: refResPath.getPathParams()) { + String[] sideEffects = new String[] {""}; + pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); + } + generatePullDataTransfer(stateGetter, refResourceName, + refResPath.getResourceHierarchy().toResourcePath(pathParams), refResourceType, + true, platformSpec, langSpec); + bDeclareClientField = true; + } } // Construct the base message. Map.Entry>>, Term> resourcePathsAndMessage; if (!isContainedPush) { // All incoming edges are in PULL-style. - resourcePathsAndMessage = ch.fillOutsideResourcePaths(out, JavaCodeGenerator.pullAccessor, null); + resourcePathsAndMessage = ch.fillOutsideResourcePaths(out, getPullAccessor(platformSpec), null); } else { // At least one incoming edge is in PUSH-style. - resourcePathsAndMessage = ch.fillOutsideResourcePaths(out, JavaCodeGenerator.pullAccessor, inputResourceToStateAccessor); + resourcePathsAndMessage = ch.fillOutsideResourcePaths(out, getPullAccessor(platformSpec), inputResourceToStateAccessor); } Map>> resourcePaths = resourcePathsAndMessage.getKey(); - Term messageTerm = resourcePathsAndMessage.getValue(); + Term messageTerm = resourcePathsAndMessage.getValue(); + + // Data transfer from path depending resource. + for (Entry>> pathEnt: resourcePaths.entrySet()) { + ChannelMember cm = pathEnt.getKey(); + ResourcePath srcResPath = pathEnt.getValue().getKey(); + // get outside srcResPath resource state by pull data transfer. + if (!platformSpec.isMonolithic() + && (cm.isOutside() + || (srcResPath.getCommonPrefix(dstResPath)) == null && platformSpec.isDifferentTreesAsDifferentServices())) { + // for REST API + // Data transfer from an outside input resource is regarded as PULL transfer. + List pathParams = new ArrayList<>(); + for (Expression pathExp: srcResPath.getPathParams()) { + String[] sideEffects = new String[] {""}; + pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); + } + // generate a pull data transfer from a depending in/ref resource. + Type srcResourceType = srcResPath.getResourceStateType(); + String srcResName2 = langSpec.toVariableName(getComponentName(srcResPath.getResourceHierarchy(), langSpec)); + String srcPath2 = srcResPath.toString().replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); + generatePullDataTransfer(stateGetter, srcResName2, srcPath2, srcResourceType, false, platformSpec, langSpec); + bDeclareClientField = true; + } + } + // Data transfer from the descendant channel hierarchies. Stack> channelItrStack = new Stack<>(); DataTransferChannel curChannel = ch; @@ -852,9 +1075,16 @@ // not a depending channel member. ResourcePath src2 = cm2.getResource(); Type srcResType2 = src2.getResourceStateType(); - String srcResName2 = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(src2.getResourceHierarchy())); - String srcGetter = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(src2, resourceNode.getInSideResource(curChannel)).toImplementation(new String[] {}); - stateGetter.addStatement(srcResType2.getInterfaceTypeName() + " " + srcResName2 + " = " + srcGetter + ";"); + String srcResName2 = langSpec.toVariableName(getComponentName(src2.getResourceHierarchy(), langSpec)); + if (platformSpec.isMonolithic()) { + String srcGetter = getPullAccessor(platformSpec).getDirectStateAccessorFor(src2, resourceNode.getInSideResource(curChannel)).toImplementation(new String[] {}); + stateGetter.addStatement(langSpec.getVariableDeclaration(srcResType2.getInterfaceTypeName(), srcResName2) + + langSpec.getAssignment() + srcGetter + langSpec.getStatementDelimiter()); + } else { + String srcPath2 = src2.toString().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); + generatePullDataTransfer(stateGetter, srcResName2, srcPath2, srcResType2, false, platformSpec, langSpec); + bDeclareClientField = true; + } } else { // a depending channel member. ResourcePath src2 = resourcePaths.get(cm2).getKey(); @@ -862,16 +1092,23 @@ if (cm2.isOutside() || src2.getCommonPrefix(resourceNode.getInSideResource(curChannel)) == null) { // generate a pull data transfer from a depending in/ref resource. Type srcResType2 = src2.getResourceStateType(); - String srcResName2 = JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(src2.getResourceHierarchy())); - String dependingGetter = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(src2, resourceNode.getInSideResource(curChannel)).toImplementation(new String[] {}); - stateGetter.addStatement(srcResType2.getInterfaceTypeName() + " " + srcResName2 + " = " + dependingGetter + ";"); + String srcResName2 = langSpec.toVariableName(getComponentName(src2.getResourceHierarchy(), langSpec)); + if (platformSpec.isMonolithic()) { + String dependingGetter = getPullAccessor(platformSpec).getDirectStateAccessorFor(src2, resourceNode.getInSideResource(curChannel)).toImplementation(new String[] {}); + stateGetter.addStatement(langSpec.getVariableDeclaration(srcResType2.getInterfaceTypeName(), srcResName2) + + langSpec.getAssignment() + dependingGetter + langSpec.getStatementDelimiter()); + } else { + String srcPath2 = src2.toString().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); + generatePullDataTransfer(stateGetter, srcResName2, srcPath2, srcResType2, false, platformSpec, langSpec); + bDeclareClientField = true; + } } } } // collect the message constraints by a descendant channel. List varsForSideEffects = new ArrayList<>(); int v = 0; - resourcePathsAndMessage = curChannel.fillOutsideResourcePaths(out, JavaCodeGenerator.pullAccessor, null); + resourcePathsAndMessage = curChannel.fillOutsideResourcePaths(out, getPullAccessor(platformSpec), null); if (resourcePathsAndMessage != null) { resourcePaths = resourcePathsAndMessage.getKey(); Term messageTermSub = resourcePathsAndMessage.getValue(); @@ -908,13 +1145,13 @@ throw new UnificationFailed(); } } - // enclosed by a for loop + // enclosed by a for loop (for data collecting pull transfer) Expression selExp = curChannel.getSelectors().get(0).getExpression(); Type selType = null; - String varName = null; + String forVarName = null; if (selExp instanceof Variable) { selType = ((Variable) selExp).getType(); - varName = ((Variable) selExp).getName(); + forVarName = ((Variable) selExp).getName(); ChannelMember insideChMem = null; for (ChannelMember cm2 :curChannel.getInputChannelMembers()) { if (!cm2.isOutside()) { @@ -935,20 +1172,46 @@ insideResPath = insideResPath.getParent(); } insideResPath = insideResPath.getParent(); - String parent = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, resourceNode.getInSideResource(curChannel)).toImplementation(new String[] {}); if (insideResPath != null) { + String parent = null; + if (platformSpec.isMonolithic() + || insideResPath.getCommonPrefix(dstResPath) != null + || !platformSpec.isDifferentTreesAsDifferentServices()) { + if (!platformSpec.isMonolithic() && generatesComponent(insideResPath.getResourceHierarchy())) { + Expression parentGetter = getPullAccessor(platformSpec).getDirectStateAccessorFor(insideResPath, dstResPath); + Term valueGetter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + valueGetter.addChild(parentGetter); + parent = valueGetter.toImplementation(new String[] {}); + } else { + parent = getPullAccessor(platformSpec).getDirectStateAccessorFor(insideResPath, dstResPath).toImplementation(new String[] {}); + } + } else { + // for REST API + parent = langSpec.toVariableName(getComponentName(insideResPath.getResourceHierarchy(), langSpec)); + } if (selType.equals(DataConstraintModel.typeInt)) { // make a for loop (for a list) for data collecting. - stateGetter.addFirstStatement("for (int " + varName + " = 0; " + varName +" < " + parent + ".size(); " + varName + "++) {"); + stateGetter.addFirstStatement(langSpec.getForStatementForList(forVarName, parent)); } else if (selType.equals(DataConstraintModel.typeString)) { // make a for loop (for a map) for data collecting. - stateGetter.addFirstStatement("for (String " + varName + ": " + parent + ".keySet()) {"); + stateGetter.addFirstStatement(langSpec.getForStatementForMap(forVarName, DataConstraintModel.typeString.getInterfaceTypeName(), parent)); + } + if (!platformSpec.isMonolithic() + && insideResPath.getCommonPrefix(dstResPath) == null + && platformSpec.isDifferentTreesAsDifferentServices()) { + // for REST API + Type parentResType = insideResPath.getResourceStateType(); + String parentResName = langSpec.toVariableName(getComponentName(insideResPath.getResourceHierarchy(), langSpec)); + String parentResPath = insideResPath.toString().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); + generatePullDataTransfer(stateGetter, parentResName, parentResPath, parentResType, true, platformSpec, langSpec); + bDeclareClientField = true; } } } // initialize the variables to hold side effects within the loop for (Variable var: varsForSideEffects) { - stateGetter.addFirstStatement(var.getType().getInterfaceTypeName() + " " + var.getName() + " = new " + var.getType().getImplementationTypeName() + "();"); + stateGetter.addFirstStatement(langSpec.getVariableDeclaration(var.getType().getInterfaceTypeName(), var.getName()) + + langSpec.getAssignment() + langSpec.getConstructorInvocation(var.getType().getImplementationTypeName(), null) + langSpec.getStatementDelimiter()); } // end of the loop stateGetter.addStatement("}"); @@ -962,12 +1225,13 @@ // generate a return statement. String[] sideEffects = new String[] {""}; - String curState = ch.deriveUpdateExpressionOf(out, messageTerm, getPullAccessor()).toImplementation(sideEffects); + String curState = ch.deriveUpdateExpressionOf(out, messageTerm, getPullAccessor(platformSpec)).toImplementation(sideEffects); stateGetter.addStatement(sideEffects[0] + langSpec.getReturnStatement(curState) + langSpec.getStatementDelimiter()); } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed | ValueUndefined e) { e.printStackTrace(); } + return bDeclareClientField; } private void declareDescendantGetterMethods(ResourceNode resourceNode, TypeDeclaration component, Map> descendantGetters, ILanguageSpecific langSpec) { @@ -1018,7 +1282,8 @@ } } - private Map.Entry, Map>>> declareCacheFieldsAndUpdateMethods(ResourceNode resourceNode, TypeDeclaration component, TypeDeclaration parentComponent, ILanguageSpecific langSpec) { + private Map.Entry, Map>>> declareCacheFieldsAndUpdateMethods(ResourceNode resourceNode, + TypeDeclaration component, TypeDeclaration parentComponent, TypeDeclaration rootComponent, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { // Declare cash fields and update methods in the component. String resComponentName = getComponentName(resourceNode.getResourceHierarchy(), langSpec); List constructorStatements = new ArrayList<>(); @@ -1055,9 +1320,11 @@ } // Check if the output resource is outside of the channel scope. boolean outsideOutputResource = false; + ChannelMember out = null; ResourcePath dstResPath = null; for (ChannelMember cm: ch.getOutputChannelMembers()) { if (resourceNode.getInSideResources().contains(cm.getResource())) { + out = cm; dstResPath = cm.getResource(); if (cm.isOutside()) { outsideOutputResource = true; // Regarded as push transfer. @@ -1073,33 +1340,44 @@ outsideInputResource = true; // Regarded as (collecting) pull transfer. } if ((((PushPullAttribute) re.getAttribute()).getSelectedOption() == PushPullValue.PUSH && !outsideInputResource) || outsideOutputResource) { - // for push data transfer + // For push data transfer + boolean hasRestAPI = false; + boolean isRestAPI = false; + if (!platformSpec.isMonolithic() + && (outsideOutputResource || (resourceNode.getInSideResource(ch).getCommonPrefix(srcResPath) == null && platformSpec.isDifferentTreesAsDifferentServices()))) { + // Inter-service + hasRestAPI = true; + if (component != null && !((RestApiSpecific) platformSpec).hasHttpClientFieldDeclaration(component)) { + // Declare a client field to connect to the destination resource of push transfer. + ((RestApiSpecific) platformSpec).addHttpClientFieldDeclaration(component); + } + if (resourceNode.getParent() == null) { + // A root resource + isRestAPI = true; + } + } // Declare an update method in the type of the destination resource. ArrayList parameters = new ArrayList<>(); - int v = 1; - for (Expression exp: dstResPath.getPathParams()) { - if (exp instanceof Variable) { - Variable pathVar = (Variable) exp; - String varName = "self" + (v > 1 ? v : ""); -// String varName = pathVar.getName(); - VariableDeclaration pathParam = langSpec.newVariableDeclaration(pathVar.getType(), varName); - parameters.add(pathParam); // A path parameter to identify the self resource. - } - v++; - } + getUpdateResourcePathAndPathParams(dstResPath, parameters, isRestAPI, platformSpec, langSpec); // Path parameters to identify the self resource. for (Selector selector: ch.getAllSelectors()) { if (selector.getExpression() instanceof Variable) { Variable selVar = (Variable) selector.getExpression(); VariableDeclaration chParam = langSpec.newVariableDeclaration(selVar.getType(), selVar.getName()); + if (isRestAPI) ((RestApiSpecific) platformSpec).addFormParamAnnotation(chParam, selVar.getName()); parameters.add(chParam); // A channel parameter to specify the context of the collaboration. } } - parameters.add(langSpec.newVariableDeclaration(srcResPath.getResourceStateType(), srcResPath.getLeafResourceName())); // The state of the source resource to carry the data-flow. + VariableDeclaration param = langSpec.newVariableDeclaration(srcResPath.getResourceStateType(), srcResName); + if (isRestAPI) ((RestApiSpecific) platformSpec).addFormParamAnnotation(param, srcResName); + parameters.add(param); // The state of the source resource to carry the data-flow. // For the refs. for (ResourcePath ref: ch.getReferenceResources()) { if (!resourceNode.getInSideResources().contains(ref)) { - parameters.add(langSpec.newVariableDeclaration(ref.getResourceStateType(), ref.getLeafResourceName())); + String refName = langSpec.toVariableName(getComponentName(ref.getResourceHierarchy(), langSpec)); + param = langSpec.newVariableDeclaration(ref.getResourceStateType(), refName); + if (isRestAPI) ((RestApiSpecific) platformSpec).addFormParamAnnotation(param, refName); + parameters.add(param); } } MethodDeclaration update = null; @@ -1112,7 +1390,6 @@ } if (update == null) { update = langSpec.newMethodDeclaration(updateMethodPrefix + from + srcResComponentName, false, null, parameters); - component.addMethod(update); } } else if (parentComponent != null) { for (MethodDeclaration method: parentComponent.getMethods()) { @@ -1123,132 +1400,273 @@ } if (update == null) { update = langSpec.newMethodDeclaration(updateMethodPrefix + resComponentName + from + srcResComponentName, false, null, parameters); + } + } + // Calculate in-degree (PUSH transfer) of the destination resource. + int inDegree = 0; + for (Edge resToCh2: inEdges) { + DataFlowEdge df =(DataFlowEdge) resToCh2; + if (((PushPullAttribute) df.getAttribute()).getSelectedOption() == PushPullValue.PUSH) { + inDegree++; + } + } + if (isRestAPI) { + // Determine whether the update method is put or post or delete. + if (isPut(out)) { + ((RestApiSpecific) platformSpec).addPutAnnotations(update); + } else { + if (!isDelete(out)) { + ((RestApiSpecific) platformSpec).addPostAnnotations(update); + } else { + ((RestApiSpecific) platformSpec).addDeleteAnnotations(update); + } + } + if (inDegree > 1) { + // If incoming edges are multiple, then a child resource for each source resource is defined in the destination resource so that its state can be updated separately. + if (isRestAPI) ((RestApiSpecific) platformSpec).addPathAnnotation(update, "/" + srcResName); + } + } + if (update != null) { + if (component != null) { + // A component is created for this resource. + component.addMethod(update); + } else if (parentComponent != null) { + // No component is created for this resource. parentComponent.addMethod(update); } } + // For a post/put REST API. + if (hasRestAPI) { + if (!isRestAPI) { + // If not a root resource. + // Declare an update accessor method in the type of root resource. + declareUpdateAccessorInTheRootResource(resourceNode, update.getName(), ch, out, srcResPath, dstResPath, + rootComponent, inDegree, platformSpec, langSpec); + } + // to convert a json param to a tuple, pair or map object. + for (VariableDeclaration jsonParam: update.getParameters()) { + Type paramType = jsonParam.getType(); + String paramName = jsonParam.getName(); + String paramTypeName = paramType.getInterfaceTypeName(); + String strTypeName = DataConstraintModel.typeString.getInterfaceTypeName(); + String paramConverter = ""; + if (DataConstraintModel.typeList.isAncestorOf(paramType) && paramType != DataConstraintModel.typeList) { + Type compType = TypeInference.getListComponentType(paramType); + if (DataConstraintModel.typeTuple.isAncestorOf(compType)) { + jsonParam.setType(DataConstraintModel.typeListStr); + jsonParam.setName(paramName + "_json"); + paramConverter += langSpec.getVariableDeclaration(paramTypeName, paramName) + langSpec.getAssignment() + langSpec.getConstructorInvocation(paramType.getImplementationTypeName(), null) + langSpec.getStatementDelimiter() + "\n"; + paramConverter += langSpec.getForStatementForCollection("str", strTypeName, jsonParam.getName()) + "\n"; + String mapTypeName = convertFromEntryToMapType(compType, langSpec); + paramConverter += "\t" + ((RestApiSpecific) platformSpec).getConversionFromJsonString("str", "i", mapTypeName) + langSpec.getStatementDelimiter() + "\n"; + paramConverter += "\t" + langSpec.getMethodInvocation(paramName, DataConstraintModel.append.getImplName(), List.of(getCodeForConversionFromMapToTuple(compType, "i", langSpec))) + langSpec.getStatementDelimiter() + "\n"; + paramConverter += langSpec.getEndForStatement("str"); + ((RestApiSpecific) platformSpec).addJsonException(update); + } else if (DataConstraintModel.typePair.isAncestorOf(compType)) { + jsonParam.setType(DataConstraintModel.typeListStr); + jsonParam.setName(paramName + "_json"); + paramConverter += langSpec.getVariableDeclaration(paramTypeName, paramName) + langSpec.getAssignment() + langSpec.getConstructorInvocation(paramType.getImplementationTypeName(), null) + langSpec.getStatementDelimiter() + "\n"; + paramConverter += langSpec.getForStatementForCollection("str", strTypeName, jsonParam.getName()) + "\n"; + String mapTypeName = convertFromEntryToMapType(compType, langSpec); + paramConverter += "\t" + ((RestApiSpecific) platformSpec).getConversionFromJsonString("str", "i", mapTypeName) + langSpec.getStatementDelimiter() + "\n"; + paramConverter += "\t" + langSpec.getMethodInvocation(paramName, DataConstraintModel.append.getImplName(), List.of(getCodeForConversionFromMapToPair(compType, "i", langSpec))) + langSpec.getStatementDelimiter() + "\n"; + paramConverter += langSpec.getEndForStatement("str"); + ((RestApiSpecific) platformSpec).addJsonException(update); + } else if (DataConstraintModel.typeMap.isAncestorOf(compType)) { + jsonParam.setType(DataConstraintModel.typeListStr); + // To do. + } + } else if (DataConstraintModel.typeTuple.isAncestorOf(paramType)) { + jsonParam.setType(DataConstraintModel.typeString); + jsonParam.setName(paramName + "_json"); + paramConverter += langSpec.getVariableDeclaration(paramTypeName, paramName) + langSpec.getStatementDelimiter() + "\n"; + paramConverter += langSpec.getOpeningScoreDelimiter() + "\n"; + String mapTypeName = convertFromEntryToMapType(paramType, langSpec); + paramConverter += "\t" + ((RestApiSpecific) platformSpec).getConversionFromJsonString(paramName + "_json", "i", mapTypeName) + langSpec.getStatementDelimiter() + "\n"; + paramConverter += "\t" + paramName + langSpec.getAssignment() + getCodeForConversionFromMapToTuple(paramType, "i", langSpec) + langSpec.getStatementDelimiter() + "\n"; + paramConverter += langSpec.getClosingScoreDelimiter(); + ((RestApiSpecific) platformSpec).addJsonException(update); + } else if (DataConstraintModel.typePair.isAncestorOf(paramType)) { + jsonParam.setType(DataConstraintModel.typeString); + jsonParam.setName(paramName + "_json"); + paramConverter += langSpec.getVariableDeclaration(paramTypeName, paramName) + langSpec.getStatementDelimiter() + "\n"; + paramConverter += langSpec.getOpeningScoreDelimiter() + "\n"; + String mapTypeName = convertFromEntryToMapType(paramType, langSpec); + paramConverter += "\t" + ((RestApiSpecific) platformSpec).getConversionFromJsonString(paramName + "_json", "i", mapTypeName) + langSpec.getStatementDelimiter() + "\n"; + paramConverter += "\t" + paramName + langSpec.getAssignment() + getCodeForConversionFromMapToPair(paramType, "i", langSpec) + langSpec.getStatementDelimiter() + "\n"; + paramConverter += langSpec.getClosingScoreDelimiter(); + ((RestApiSpecific) platformSpec).addJsonException(update); + } else if (DataConstraintModel.typeMap.isAncestorOf(paramType)) { + jsonParam.setType(DataConstraintModel.typeString); + jsonParam.setName(paramName + "_json"); + paramConverter += langSpec.getVariableDeclaration(paramTypeName, paramName) + langSpec.getAssignment() + langSpec.getConstructorInvocation(paramType.getImplementationTypeName(), null) + langSpec.getStatementDelimiter() + "\n"; + paramConverter += langSpec.getOpeningScoreDelimiter() + "\n"; + String mapTypeName = convertFromEntryToMapType(paramType, langSpec); + paramConverter += "\t" + ((RestApiSpecific) platformSpec).getConversionFromJsonString(paramName + "_json", "i", mapTypeName) + langSpec.getStatementDelimiter() + "\n"; + paramConverter += "\t" + getCodeForConversionFromMapToMap(paramType, "i", paramName, langSpec) + "\n"; + paramConverter += langSpec.getClosingScoreDelimiter(); + ((RestApiSpecific) platformSpec).addJsonException(update); + } + if (paramConverter.length() > 0 && !update.getBody().getStatements().contains(paramConverter)) { + update.addFirstStatement(paramConverter); + } + } + } // Add a statement to update the state field if (((StoreAttribute) resourceNode.getAttribute()).isStored()) { try { - for (ChannelMember out: ch.getOutputChannelMembers()) { - if (resourceNode.getInSideResources().contains(out.getResource())) { - Expression updateExp = null; - if (ch.getReferenceChannelMembers().size() == 0) { - updateExp = ch.deriveUpdateExpressionOf(out, getPushAccessor()).getKey(); + if (resourceNode.getInSideResources().contains(out.getResource())) { + Term unifiedMassage = null; + for (ChannelNode srcChNode: ancestorSrcChannels) { + DataTransferChannel abcestorSrcCh = (DataTransferChannel) srcChNode.getChannel(); + Term message = abcestorSrcCh.fillOutsideResourcePaths(out, getPushAccessor(platformSpec), null).getValue(); + if (unifiedMassage == null) { + unifiedMassage = message; } else { - // if there exists one or more reference channel member. - HashMap inputResourceToStateAccessor = new HashMap<>(); - for (ChannelMember in: ch.getInputChannelMembers()) { - inputResourceToStateAccessor.put(in, getPushAccessor()); - } - for (ChannelMember c: ch.getReferenceChannelMembers()) { - inputResourceToStateAccessor.put(c, getRefAccessor()); - } - updateExp = ch.deriveUpdateExpressionOf(out, getPushAccessor(), inputResourceToStateAccessor).getKey(); + unifiedMassage = (Term) unifiedMassage.unify(message); } - // Replace Json constructor with a constructor of the child resource. - ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); - if (outRes.getChildren().size() == 1 && outRes.getChildren().iterator().next().getNumParameters() > 0) { - ResourceHierarchy descendantRes = outRes; - Set children = descendantRes.getChildren(); - do { - descendantRes = children.iterator().next(); - if (generatesComponent(descendantRes)) { - updateStatements.put(update, new AbstractMap.SimpleEntry<>(updateExp, new AbstractMap.SimpleEntry<>(outRes, descendantRes))); - updateExp = null; - break; - } - children = descendantRes.getChildren(); - } while (children != null && children.size() == 1); + } + Expression updateExp = null; + if (ch.getReferenceChannelMembers().size() == 0) { + Term message = ch.fillOutsideResourcePaths(out, getPushAccessor(platformSpec), null).getValue(); + if (unifiedMassage == null) { + unifiedMassage = message; + } else { + unifiedMassage = (Term) unifiedMassage.unify(message); } - // Add statements to the update method. - String[] sideEffects = new String[] {""}; - String newState = updateExp.toImplementation(sideEffects); - int numOfOutResourcesWithTheSameHierarchy = 0; - for (ResourcePath outResPath: ch.getOutputResources()) { - if (outResPath.getResourceHierarchy().equals(outRes)) { - numOfOutResourcesWithTheSameHierarchy++; + updateExp = ch.deriveUpdateExpressionOf(out, unifiedMassage, getPushAccessor(platformSpec)); + } else { + // if there exists one or more reference channel member. + HashMap inputResourceToStateAccessor = new HashMap<>(); + for (ChannelMember in: ch.getInputChannelMembers()) { + inputResourceToStateAccessor.put(in, getPushAccessor(platformSpec)); + } + for (ChannelMember ref: ch.getReferenceChannelMembers()) { + inputResourceToStateAccessor.put(ref, getRefAccessor(platformSpec)); + } + Term message = ch.fillOutsideResourcePaths(out, getPushAccessor(platformSpec), inputResourceToStateAccessor).getValue(); + if (unifiedMassage == null) { + unifiedMassage = message; + } else { + unifiedMassage = (Term) unifiedMassage.unify(message); + } + updateExp = ch.deriveUpdateExpressionOf(out, unifiedMassage, getPushAccessor(platformSpec)); + } + // Replace Json constructor with a constructor of the child resource. + ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); + if (outRes.getChildren().size() == 1 && outRes.getChildren().iterator().next().getNumParameters() > 0) { + ResourceHierarchy descendantRes = outRes; + Set children = descendantRes.getChildren(); + do { + descendantRes = children.iterator().next(); + if (generatesComponent(descendantRes)) { + updateStatements.put(update, new AbstractMap.SimpleEntry<>(updateExp, new AbstractMap.SimpleEntry<>(outRes, descendantRes))); + updateExp = null; + break; + } + children = descendantRes.getChildren(); + } while (children != null && children.size() == 1); + } + // Replace the type of the state field. + Type fieldType = getImplStateType(outRes, langSpec); + if (updateExp instanceof Term) { + ((Term) updateExp).setType(fieldType); + for (Map.Entry varEnt: ((Term) updateExp).getVariables().entrySet()) { + if (varEnt.getValue().getName().equals(fieldOfResourceState)) { + varEnt.getValue().setType(fieldType); } } - String updateStatement = ""; - if (generatesComponent(outRes)) { - if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { - updateStatement = sideEffects[0]; - if (updateStatement.endsWith("\n")) { - updateStatement = updateStatement.substring(0, updateStatement.length() - 1); - } - } else { - updateStatement = sideEffects[0] + langSpec.getFieldAccessor(fieldOfResourceState) + langSpec.getAssignment() + newState + langSpec.getStatementDelimiter(); // this.value = ... + } else if (updateExp instanceof Variable) { + ((Variable) updateExp).setType(fieldType); + } + // Add statements to the update method. + String[] sideEffects = new String[] {""}; + String newState = updateExp.toImplementation(sideEffects); + int numOfOutResourcesWithTheSameHierarchy = 0; + for (ResourcePath outResPath: ch.getOutputResources()) { + if (outResPath.getResourceHierarchy().equals(outRes)) { + numOfOutResourcesWithTheSameHierarchy++; + } + } + String updateStatement = ""; + if (generatesComponent(outRes)) { + if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { + updateStatement = sideEffects[0]; + if (updateStatement.endsWith("\n")) { + updateStatement = updateStatement.substring(0, updateStatement.length() - 1); } } else { - if (sideEffects[0] != null) { - updateStatement = sideEffects[0]; - String resourceName = langSpec.toVariableName(getComponentName(outRes, langSpec)); - updateStatement = updateStatement.replace(langSpec.getFieldAccessor(fieldOfResourceState), langSpec.getFieldAccessor(resourceName)); - if (updateStatement.endsWith("\n")) { - updateStatement = updateStatement.substring(0, updateStatement.length() - 1); - } - } - if (DataConstraintModel.typeList.isAncestorOf(resourceNode.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.set); - selector.addChild(new Constant(langSpec.getFieldAccessor(fieldOfResourceState))); - selector.addChild(new Variable(update.getParameters().get(update.getParameters().size() - 2).getName())); - selector.addChild(new Constant(newState)); - String[] sideEffects2 = new String[] {""}; - String newList = selector.toImplementation(sideEffects2); - updateStatement += sideEffects2[0]; - } else if (DataConstraintModel.typeMap.isAncestorOf(resourceNode.getParent().getResourceStateType())) { - Term selector = new Term(DataConstraintModel.insert); - selector.addChild(new Constant(langSpec.getFieldAccessor(fieldOfResourceState))); - selector.addChild(new Variable(update.getParameters().get(update.getParameters().size() - 2).getName())); - selector.addChild(new Constant(newState)); - String[] sideEffects2 = new String[] {""}; - String newMap = selector.toImplementation(sideEffects2); - updateStatement += sideEffects2[0]; - } else if (!(updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect())) { - String resourceName = langSpec.toVariableName(getComponentName(outRes, langSpec)); - updateStatement += langSpec.getFieldAccessor(resourceName) + langSpec.getAssignment() + newState + langSpec.getStatementDelimiter(); + updateStatement = sideEffects[0] + langSpec.getFieldAccessor(fieldOfResourceState) + langSpec.getAssignment() + newState + langSpec.getStatementDelimiter(); // this.value = ... + } + } else { + if (sideEffects[0] != null) { + updateStatement = sideEffects[0]; + String resourceName = langSpec.toVariableName(getComponentName(outRes, langSpec)); + updateStatement = updateStatement.replace(langSpec.getFieldAccessor(fieldOfResourceState), langSpec.getFieldAccessor(resourceName)); + if (updateStatement.endsWith("\n")) { + updateStatement = updateStatement.substring(0, updateStatement.length() - 1); } } - if (numOfOutResourcesWithTheSameHierarchy == 1) { - update.addFirstStatement(updateStatement); - } else { - Term conditions = null; - int i = 1; - Map>> resourcePaths = ch.fillOutsideResourcePaths(out, JerseyCodeGenerator.pushAccessor); - for (Expression pathParam: out.getResource().getPathParams()) { - if (pathParam instanceof Variable) { - String selfParamName = ((Variable) pathParam).getName(); - Expression arg = null; - for (Selector selector: ch.getAllSelectors()) { - if (selector.getExpression() instanceof Variable) { - Variable selVar = (Variable) selector.getExpression(); - if (selVar.getName().equals(selfParamName)) { - arg = selVar; - break; - } + if (DataConstraintModel.typeList.isAncestorOf(resourceNode.getParent().getResourceStateType())) { + Term selector = new Term(DataConstraintModel.set); + selector.addChild(new Constant(langSpec.getFieldAccessor(fieldOfResourceState))); + selector.addChild(new Variable(update.getParameters().get(update.getParameters().size() - 2).getName())); + selector.addChild(new Constant(newState)); + String[] sideEffects2 = new String[] {""}; + String newList = selector.toImplementation(sideEffects2); + updateStatement += sideEffects2[0]; + } else if (DataConstraintModel.typeMap.isAncestorOf(resourceNode.getParent().getResourceStateType())) { + Term selector = new Term(DataConstraintModel.insert); + selector.addChild(new Constant(langSpec.getFieldAccessor(fieldOfResourceState))); + selector.addChild(new Variable(update.getParameters().get(update.getParameters().size() - 2).getName())); + selector.addChild(new Constant(newState)); + String[] sideEffects2 = new String[] {""}; + String newMap = selector.toImplementation(sideEffects2); + updateStatement += sideEffects2[0]; + } else if (!(updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect())) { + String resourceName = langSpec.toVariableName(getComponentName(outRes, langSpec)); + updateStatement += langSpec.getFieldAccessor(resourceName) + langSpec.getAssignment() + newState + langSpec.getStatementDelimiter(); + } + } + // add an update statement of the state of dst side resource. + if (numOfOutResourcesWithTheSameHierarchy == 1) { + update.addFirstStatement(updateStatement); + } else { + Term conditions = null; + int i = 1; + Map>> resourcePaths = ch.fillOutsideResourcePaths(out, getPushAccessor(platformSpec)); + for (Expression pathParam: out.getResource().getPathParams()) { + if (pathParam instanceof Variable) { + String selfParamName = ((Variable) pathParam).getName(); + Expression arg = null; + for (Selector selector: ch.getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable selVar = (Variable) selector.getExpression(); + if (selVar.getName().equals(selfParamName)) { + arg = selVar; + break; } } - if (arg == null) { - ResourcePath filledPath = resourcePaths.get(out).getKey(); - arg = filledPath.getPathParams().get(i - 1); - } - Term condition = new Term(DataConstraintModel.eq, new Expression[] { - new Parameter("self" + (i > 1 ? i : ""), DataConstraintModel.typeString), - arg}); - if (conditions == null) { - conditions = condition; - } else { - conditions = new Term(DataConstraintModel.and, new Expression[] { - conditions, - condition}); - } } - i++; + if (arg == null) { + ResourcePath filledPath = resourcePaths.get(out).getKey(); + arg = filledPath.getPathParams().get(i - 1); + } + Term condition = new Term(DataConstraintModel.eq, new Expression[] { + new Parameter("self" + (i > 1 ? i : ""), DataConstraintModel.typeString), + arg}); + if (conditions == null) { + conditions = condition; + } else { + conditions = new Term(DataConstraintModel.and, new Expression[] { + conditions, + condition}); + } } - update.addFirstStatement(langSpec.getIfStatement(conditions, updateStatement)); + i++; } - break; + update.addFirstStatement(langSpec.getIfStatement(conditions, updateStatement)); } } } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork @@ -1258,14 +1676,15 @@ } // Declare the field to cache the state of the source resource in the type of the destination resource. - if (resToCh.getDestination().getIndegree() + ch.getInputChannelMembers().size() > 1 + if (inDegree > 1 || (ch.getInputChannelMembers().size() == 1 && ch.getInputChannelMembers().iterator().next().getStateTransition().isRightPartial())) { // If incoming edges are multiple, or the current state of an input member is needed. if (langSpec.declareField()) { // Declare the cache field. + String cacheFieldName = langSpec.toVariableName(getComponentName(srcResPath.getResourceHierarchy(), langSpec)); FieldDeclaration cacheField = langSpec.newFieldDeclaration( srcResPath.getResourceStateType(), - srcResPath.getLeafResourceName(), + cacheFieldName, langSpec.getFieldInitializer(srcResPath.getResourceStateType(), srcResPath.getResourceHierarchy().getInitialValue())); if (component != null) { component.addField(cacheField); @@ -1281,54 +1700,58 @@ } } - Set outsideInputMembers = new HashSet<>(); - for (ChannelMember cm: ch.getInputChannelMembers()) { - if (cm.isOutside()) { - outsideInputMembers.add(cm); - } - } - if (outsideInputMembers.size() > 0) { - Map>> resourcePaths = null; - for (ChannelMember out: ch.getOutputChannelMembers()) { - if (resourceNode.getInSideResources().contains(out.getResource())) { - try { - resourcePaths = ch.fillOutsideResourcePaths(out, getPullAccessor()); - } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork - | InvalidMessage | UnificationFailed | ValueUndefined e) { - e.printStackTrace(); - } - break; + // Update and initialize a field to refer to an outside input resource for PULL transfer. + if (platformSpec.isMonolithic()) { + // For a monolithic application. + Set outsideInputMembers = new HashSet<>(); + for (ChannelMember cm: ch.getInputChannelMembers()) { + if (cm.isOutside()) { + outsideInputMembers.add(cm); } } - if (resourcePaths != null && resourcePaths.size() > 0) { - for (ChannelMember outsideMember: outsideInputMembers) { - for (ChannelMember dependingMember: resourcePaths.get(outsideMember).getValue()) { - if (dependingMember.getResource().equals(srcResPath)) { - // An outside input resource path depends on srcRes. - ResourcePath outsidePath = resourcePaths.get(outsideMember).getKey(); - String outsideResName = langSpec.toVariableName(getComponentName(outsidePath.getResourceHierarchy(), langSpec)); - Expression outsideExp = getPullAccessor().getDirectStateAccessorFor(outsidePath, null); - if (generatesComponent(outsidePath.getResourceHierarchy())) { - outsideExp = ((Term) outsideExp).getChild(0); - } - Expression nextExp = dependingMember.getStateTransition().getNextStateExpression(); - if (nextExp != null && outsideExp instanceof Term) { - if (nextExp instanceof Variable) { - outsideExp = ((Term) outsideExp).substitute((Variable) nextExp, new Field(langSpec.toVariableName(getComponentName(dependingMember.getResource().getResourceHierarchy(), langSpec)))); - } else { - // ToDo. + if (outsideInputMembers.size() > 0) { + Map>> resourcePaths = null; + for (ChannelMember out1: ch.getOutputChannelMembers()) { + if (resourceNode.getInSideResources().contains(out1.getResource())) { + try { + resourcePaths = ch.fillOutsideResourcePaths(out1, getPullAccessor(platformSpec)); + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined e) { + e.printStackTrace(); + } + break; + } + } + if (resourcePaths != null && resourcePaths.size() > 0) { + for (ChannelMember outsideMember: outsideInputMembers) { + for (ChannelMember dependingMember: resourcePaths.get(outsideMember).getValue()) { + if (dependingMember.getResource().equals(srcResPath)) { + // An outside input resource path depends on srcRes. + ResourcePath outsidePath = resourcePaths.get(outsideMember).getKey(); + String outsideResName = langSpec.toVariableName(getComponentName(outsidePath.getResourceHierarchy(), langSpec)); + Expression outsideExp = getPullAccessor(platformSpec).getDirectStateAccessorFor(outsidePath, null); + if (generatesComponent(outsidePath.getResourceHierarchy())) { + outsideExp = ((Term) outsideExp).getChild(0); } - } - String[] sideEffects = new String[] {""}; - String outsideAccessor = outsideExp.toImplementation(sideEffects); - String updateReference = langSpec.getFieldAccessor(outsideResName) + langSpec.getAssignment() + outsideAccessor + langSpec.getStatementDelimiter(); - update.addStatement(updateReference); // Update the reference field. - // Update constructor. - if (component != null) { - MethodDeclaration constructor = getConstructor(component); - constructor.addStatement(updateReference); // Initialize the reference field. - } else if (parentComponent != null){ - constructorStatements.add(updateReference); + Expression nextExp = dependingMember.getStateTransition().getNextStateExpression(); + if (nextExp != null && outsideExp instanceof Term) { + if (nextExp instanceof Variable) { + outsideExp = ((Term) outsideExp).substitute((Variable) nextExp, new Field(langSpec.toVariableName(getComponentName(dependingMember.getResource().getResourceHierarchy(), langSpec)))); + } else { + // ToDo. + } + } + String[] sideEffects = new String[] {""}; + String outsideAccessor = outsideExp.toImplementation(sideEffects); + String updateReference = langSpec.getFieldAccessor(outsideResName) + langSpec.getAssignment() + outsideAccessor + langSpec.getStatementDelimiter(); + update.addStatement(updateReference); // Update the reference field. + // Update constructor. + if (component != null) { + MethodDeclaration constructor = getConstructor(component); + constructor.addStatement(updateReference); // Initialize the reference field. + } else if (parentComponent != null){ + constructorStatements.add(updateReference); + } } } } @@ -1337,6 +1760,7 @@ } // Add an invocation to another update method (for a chain of update method invocations). + boolean hasUpdateMethodinvoked = false; for (Edge resToCh2: resourceNode.getOutEdges()) { DataFlowEdge dOut = (DataFlowEdge) resToCh2; ChannelNode directDstChNode = (ChannelNode) resToCh2.getDestination(); @@ -1374,10 +1798,10 @@ DataTransferChannel ch2 = chNode2.getChannel(); // Check if the output resource is outside of the channel scope. boolean outsideOutputResource2 = false; - ChannelMember out = null; + ChannelMember out1 = null; for (ChannelMember cm: ch2.getOutputChannelMembers()) { if (dstNode.getInSideResources().contains(cm.getResource())) { - out = cm; + out1 = cm; if (cm.isOutside()) { outsideOutputResource2 = true; break; @@ -1431,17 +1855,41 @@ insideResPath = insideResPath.getParent(); } insideResPath = insideResPath.getParent(); - String parent = getPullAccessor().getDirectStateAccessorFor(insideResPath, resourceNode.getPrimaryResourcePath()).toImplementation(new String[] {}); if (insideResPath != null) { + String parent = null; + if (platformSpec.isMonolithic() + || insideResPath.getCommonPrefix(resourceNode.getOutSideResource(directDstCh)) != null + || !platformSpec.isDifferentTreesAsDifferentServices()) { + if (!platformSpec.isMonolithic() && generatesComponent(insideResPath.getResourceHierarchy())) { + Expression getter = getPullAccessor(platformSpec).getDirectStateAccessorFor(insideResPath, resourceNode.getOutSideResource(directDstCh)); + Term valueGetter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + valueGetter.addChild(getter); + parent = valueGetter.toImplementation(new String[] {}); + } else { + parent = getPullAccessor(platformSpec).getDirectStateAccessorFor(insideResPath, resourceNode.getOutSideResource(directDstCh)).toImplementation(new String[] {}); + } + } else { + // for REST API + parent = langSpec.toVariableName(getComponentName(insideResPath.getResourceHierarchy(), langSpec)); + } if (selType.equals(DataConstraintModel.typeInt)) { // make a for loop (for a list) for broadcasting. - update.addStatement(langSpec.getForStatement(forVarName, parent)); + update.addStatement(langSpec.getForStatementForList(forVarName, parent)); addForStatement = true; } else if (selType.equals(DataConstraintModel.typeString)) { // make a for loop (for a map) for broadcasting. - update.addStatement(langSpec.getForStatement(forVarName, DataConstraintModel.typeString.getInterfaceTypeName(), parent)); + update.addStatement(langSpec.getForStatementForMap(forVarName, DataConstraintModel.typeString.getInterfaceTypeName(), parent)); addForStatement = true; } + if (!platformSpec.isMonolithic() + && insideResPath.getCommonPrefix(resourceNode.getOutSideResource(directDstCh)) == null + && platformSpec.isDifferentTreesAsDifferentServices()) { + // for REST API + Type parentResType = insideResPath.getResourceStateType(); + String parentResName = langSpec.toVariableName(getComponentName(insideResPath.getResourceHierarchy(), langSpec)); + String parentResPath = insideResPath.toString().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); + generatePullDataTransfer(update, parentResName, parentResPath, parentResType, true, platformSpec, langSpec); + } } } else if (selExp instanceof Term) { // not supported. @@ -1449,7 +1897,7 @@ } } // Get the value of reference member to call the update method. - List params = new ArrayList<>(); + List>> refParams = new ArrayList<>(); Map> referredResources = new HashMap<>(); Set referredSet = referredResources.get(update); for (ChannelMember rc: ch2.getReferenceChannelMembers()) { @@ -1460,99 +1908,209 @@ } if (!resourceNode.getInSideResources().contains(ref)) { String refVarName = langSpec.toVariableName(getComponentName(ref.getResourceHierarchy(), langSpec)); + Type refResourceType = ref.getResourceStateType(); if (!referredSet.contains(ref)) { referredSet.add(ref); - ResourcePath srcRes = in.getResource(); - if (!generatesComponent(srcRes.getResourceHierarchy())) { - srcRes = srcRes.getParent(); - } - Expression refGetter = getPullAccessor().getDirectStateAccessorFor(ref, srcRes); String[] sideEffects = new String[] {""}; - String refExp = refGetter.toImplementation(sideEffects); - String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); - update.addStatement(sideEffects[0] + langSpec.getVariableDeclaration(refTypeName, refVarName) + langSpec.getAssignment() + refExp + langSpec.getStatementDelimiter()); - } - params.add(refVarName); - } - } - // Update fields to refer to outside resources. - try { - Map>> resourcePaths = ch2.fillOutsideResourcePaths(out, getPullAccessor()); - if (resourcePaths != null && resourcePaths.size() > 0) { - for (ChannelMember outsideMember: resourcePaths.keySet()) { - ResourcePath outsidePath = resourcePaths.get(outsideMember).getKey(); - if (!generatesComponent(outsidePath.getResourceHierarchy())) { - outsidePath = outsidePath.getParent(); - } - String outsideResName = langSpec.toVariableName(getComponentName(outsidePath.getResourceHierarchy(), langSpec)); - Expression outsideExp = getPullAccessor().getDirectStateAccessorFor(outsidePath, null); - if (generatesComponent(outsidePath.getResourceHierarchy())) { - outsideExp = ((Term) outsideExp).getChild(0); - } - if (outsideExp instanceof Field) { - outsideExp = new Variable(((Field) outsideExp).getSymbol().getName(), ((Field) outsideExp).getType()); - } else if (outsideExp instanceof Term) { - for (Entry fieldEnt: ((Term) outsideExp).getSubTerms(Field.class).entrySet()) { - Position pos = fieldEnt.getKey(); - Field field = fieldEnt.getValue(); - Variable var = new Variable(field.getSymbol().getName(), field.getType()); - ((Term) outsideExp).replaceSubTerm(pos, var); + if (!platformSpec.isMonolithic() && rc.isOutside()) { + List pathParams = new ArrayList<>(); + for (Expression pathExp: ref.getPathParams()) { + pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); } + generatePullDataTransfer(update, refVarName, ref.getResourceHierarchy().toResourcePath(pathParams), refResourceType, false, platformSpec, langSpec); + } else { + ResourcePath srcRes = in.getResource(); + if (!generatesComponent(srcRes.getResourceHierarchy())) { + srcRes = srcRes.getParent(); + } + Expression refGetter = getPullAccessor(platformSpec).getDirectStateAccessorFor(ref, srcRes); + String refExp = refGetter.toImplementation(sideEffects); + String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); + update.addStatement(sideEffects[0] + langSpec.getVariableDeclaration(refTypeName, refVarName) + langSpec.getAssignment() + refExp + langSpec.getStatementDelimiter()); } - String[] sideEffects = new String[] {""}; - String outsideAccessor = outsideExp.toImplementation(sideEffects); - update.addStatement(langSpec.getFieldAccessor(outsideResName) + langSpec.getAssignment() + outsideAccessor + langSpec.getStatementDelimiter()); // change the reference field. + } + refParams.add(new AbstractMap.SimpleEntry<>(ref.getResourceStateType(), + new AbstractMap.SimpleEntry<>(refVarName, + refVarName))); + } + } + List>> pathParams = new ArrayList<>(); + if (platformSpec.isMonolithic()) { + // Update fields to refer to outside resources. + ResourcePath filledOutsideResourcePath = null; + try { + Map>> resourcePaths = ch2.fillOutsideResourcePaths(out1, getPullAccessor(platformSpec)); + if (resourcePaths != null && resourcePaths.size() > 0) { + for (ChannelMember outsideMember: resourcePaths.keySet()) { + ResourcePath outsidePath = resourcePaths.get(outsideMember).getKey(); + if (out1.equals(outsideMember)) { + filledOutsideResourcePath = outsidePath; + } + if (!generatesComponent(outsidePath.getResourceHierarchy())) { + outsidePath = outsidePath.getParent(); + } + String outsideResName = langSpec.toVariableName(getComponentName(outsidePath.getResourceHierarchy(), langSpec)); + Expression outsideExp = getPullAccessor(platformSpec).getDirectStateAccessorFor(outsidePath, null); + if (generatesComponent(outsidePath.getResourceHierarchy())) { + outsideExp = ((Term) outsideExp).getChild(0); + } + if (outsideExp instanceof Field) { + outsideExp = new Variable(((Field) outsideExp).getSymbol().getName(), ((Field) outsideExp).getType()); + } else if (outsideExp instanceof Term) { + for (Entry fieldEnt: ((Term) outsideExp).getSubTerms(Field.class).entrySet()) { + Position pos = fieldEnt.getKey(); + Field field = fieldEnt.getValue(); + Variable var = new Variable(field.getSymbol().getName(), field.getType()); + ((Term) outsideExp).replaceSubTerm(pos, var); + } + } + String[] sideEffects = new String[] {""}; + String outsideAccessor = outsideExp.toImplementation(sideEffects); + update.addStatement(langSpec.getFieldAccessor(outsideResName) + langSpec.getAssignment() + outsideAccessor + langSpec.getStatementDelimiter()); // change the reference field. + } + } + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined e) { + e.printStackTrace(); + } + // Values of path parameters to call the update method. + if (filledOutsideResourcePath == null) { + filledOutsideResourcePath = out1.getResource(); + } + for (Expression pathParam: filledOutsideResourcePath.getPathParams()) { + if (pathParam instanceof Variable) { + Variable pathVar = (Variable) pathParam; + pathParams.add(new AbstractMap.SimpleEntry<>(pathVar.getType(), + new AbstractMap.SimpleEntry<>(pathVar.getName(), + pathVar.getName()))); + } else if (pathParam instanceof Constant) { + Constant pathVar = (Constant) pathParam; + pathParams.add(new AbstractMap.SimpleEntry<>(pathVar.getType(), + new AbstractMap.SimpleEntry<>(pathVar.getSymbol().getName(), + pathVar.getSymbol().getName()))); } } - } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork - | InvalidMessage | UnificationFailed | ValueUndefined e) { - e.printStackTrace(); - } - // Values of path parameters to call the update method. - for (Expression pathParam: out.getResource().getPathParams()) { - if (pathParam instanceof Variable) { - Variable pathVar = (Variable) pathParam; - params.add(pathVar.getName()); + } else { + // Values of path parameters to call the update method. + for (Expression pathParam: out1.getResource().getPathParams()) { + if (pathParam instanceof Variable) { + Variable pathVar = (Variable) pathParam; + pathParams.add(new AbstractMap.SimpleEntry<>(pathVar.getType(), + new AbstractMap.SimpleEntry<>(pathVar.getName(), + pathVar.getName()))); + } } } // Values of channel parameters to call the update method. - for (Selector selector: ch.getAllSelectors()) { + List>> params = new ArrayList<>(); + for (Selector selector: ch2.getAllSelectors()) { if (selector.getExpression() instanceof Variable) { Variable selVar = (Variable) selector.getExpression(); - params.add(selVar.getName()); + params.add(new AbstractMap.SimpleEntry<>(selVar.getType(), + new AbstractMap.SimpleEntry<>(selVar.getName(), + selVar.getName()))); } } // Value of the source side (input side) resource to call the update method. ResourceHierarchy srcRes2 = resourceNode.getResourceHierarchy(); if (generatesComponent(srcRes2)) { - params.add(langSpec.getFieldAccessor(fieldOfResourceState)); + params.add(new AbstractMap.SimpleEntry<>(srcRes2.getResourceStateType(), + new AbstractMap.SimpleEntry<>(langSpec.toVariableName(srcRes2.getResourceName()), + langSpec.getFieldAccessor(fieldOfResourceState)))); } else { - params.add(langSpec.getFieldAccessor(langSpec.toVariableName(srcRes2.getResourceName()))); + params.add(new AbstractMap.SimpleEntry<>(srcRes2.getResourceStateType(), + new AbstractMap.SimpleEntry<>(langSpec.toVariableName(srcRes2.getResourceName()), + langSpec.getFieldAccessor(langSpec.toVariableName(srcRes2.getResourceName()))))); srcRes2 = srcRes2.getParent(); } + params.addAll(refParams); // Call the update method. String updateMethodName = null; ResourceHierarchy dstRes = dstNode.getResourceHierarchy(); if (!generatesComponent(dstRes)) { - updateMethodName = updateMethodPrefix + getComponentName(dstRes, langSpec) + from + resComponentName; + updateMethodName = updateMethodPrefix + getComponentName(dstRes, langSpec) + from + resComponentName; dstRes = dstRes.getParent(); } else { updateMethodName = updateMethodPrefix + from + resComponentName; } String dstCompName = langSpec.toVariableName(getComponentName(dstRes, langSpec)); - if (!outsideOutputResource2) { - // The destination resource is not outside. - if (srcRes2 != dstRes) { - update.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstCompName), updateMethodName, params) - + langSpec.getStatementDelimiter()); // this.dst.updateDstFromSrc(value, refParams); + if (outsideOutputResource2 + || (!platformSpec.isMonolithic() && in.getResource().getCommonPrefix(out1.getResource()) == null && platformSpec.isDifferentTreesAsDifferentServices())) { + // Inter-servces + if (!platformSpec.isMonolithic()) { + // REST API + RestApiSpecific restApiSpec = (RestApiSpecific) platformSpec; + String httpMethod = null; + if (out1.getStateTransition().isRightUnary()) { + httpMethod = "put"; + } else { + httpMethod = "post"; + } + String[] sideEffects = new String[] {""}; + List pathParamsUrl = new ArrayList<>(); + for (Expression pathExp: out1.getResource().getPathParams()) { + pathParamsUrl.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); + } + String resName = langSpec.toVariableName(resComponentName); + if (inDegree <= 1) { + resName = null; + } + Map>> filledPaths = null; + try { + filledPaths = ch2.fillOutsideResourcePaths(out1, getPushAccessor(platformSpec)); + } catch (ParameterizedIdentifierIsFutureWork + | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage + | UnificationFailed | ValueUndefined e) { + e.printStackTrace(); + } + String dstPath = null; + if (filledPaths != null && filledPaths.get(out1) != null) { + ResourcePath filledDstPath = filledPaths.get(out1).getKey(); + dstPath = filledDstPath.toString().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); + } else { + dstPath = dstRes.toResourcePath(pathParamsUrl); + } + // Call the update method. + if (!hasUpdateMethodinvoked) { + // The first call to an update method in this method + update.addStatement(restApiSpec.getHttpMethodParamsConstructionStatement(srcRes2.getResourceName(), params, true)); + update.addStatement(langSpec.getVariableDeclaration(DataConstraintModel.typeString.getInterfaceTypeName(), "result") + + langSpec.getAssignment() + restApiSpec.getHttpMethodCallStatement(restApiSpec.getBaseURL(), dstPath, resName, httpMethod)); + hasUpdateMethodinvoked = true; + } else { + // After the second time of call to update methods in this method + update.addStatement(restApiSpec.getHttpMethodParamsConstructionStatement(srcRes2.getResourceName(), params, false)); + update.addStatement("result" + langSpec.getAssignment() + restApiSpec.getHttpMethodCallStatement(restApiSpec.getBaseURL(), dstPath, resName, httpMethod)); + } } else { - update.addStatement(langSpec.getMethodInvocation(updateMethodName, params) - + langSpec.getStatementDelimiter()); // this.updateDstFromSrc(value, refParams); + // Use the reference field to refer to outside destination resource. + List args = new ArrayList<>(); + for (Map.Entry> paramEnt: pathParams) { + args.add(paramEnt.getValue().getValue()); + } + for (Map.Entry> paramEnt: params) { + args.add(paramEnt.getValue().getValue()); + } + update.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstCompName), updateMethodName, args) + + langSpec.getStatementDelimiter()); // this.dst.updateDstFromSrc(value, refParams); } } else { - // Use the reference field to refer to outside destination resource. - update.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstCompName), updateMethodName, params) - + langSpec.getStatementDelimiter()); // this.dst.updateDstFromSrc(value, refParams); + // Intra-service + // The destination resource is not outside. + List args = new ArrayList<>(); + for (Map.Entry> paramEnt: pathParams) { + args.add(paramEnt.getValue().getValue()); + } + for (Map.Entry> paramEnt: params) { + args.add(paramEnt.getValue().getValue()); + } + if (srcRes2 != dstRes) { + update.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstCompName), updateMethodName, args) + + langSpec.getStatementDelimiter()); // this.dst.updateDstFromSrc(value, refParams); + } else { + update.addStatement(langSpec.getMethodInvocation(updateMethodName, args) + + langSpec.getStatementDelimiter()); // this.updateDstFromSrc(value, refParams); + } } if (addForStatement) { // Close the for loop @@ -1567,14 +2125,14 @@ for (Edge chToRes2: outEdges) { ChannelNode chNode2 = (ChannelNode) chToRes2.getSource(); DataTransferChannel ch2 = chNode2.getChannel(); - for (ChannelMember out: ch2.getOutputChannelMembers()) { - if (!generatesComponent(out.getResource().getResourceHierarchy())) { + for (ChannelMember out2: ch2.getOutputChannelMembers()) { + if (!generatesComponent(out2.getResource().getResourceHierarchy())) { // Also dstRes2 does not have a component. - ResourcePath dstRes2 = out.getResource(); + ResourcePath dstRes2 = out2.getResource(); if (srcRes2.getParent().equals(dstRes2.getParent())) { Map>> resourcePaths = null; try { - resourcePaths = ch2.fillOutsideResourcePaths(out, getPullAccessor()); + resourcePaths = ch2.fillOutsideResourcePaths(out2, getPullAccessor(platformSpec)); if (resourcePaths != null && resourcePaths.size() > 0) { for (ChannelMember outsideMember: outsideInputMembers2) { for (ChannelMember dependedMember: resourcePaths.get(outsideMember).getValue()) { @@ -1585,7 +2143,7 @@ outsidePath = outsidePath.getParent(); } String outsideResName = langSpec.toVariableName(getComponentName(outsidePath.getResourceHierarchy(), langSpec)); - Expression outsideExp = getPullAccessor().getDirectStateAccessorFor(outsidePath, null); + Expression outsideExp = getPullAccessor(platformSpec).getDirectStateAccessorFor(outsidePath, null); if (generatesComponent(outsidePath.getResourceHierarchy())) { outsideExp = ((Term) outsideExp).getChild(0); } @@ -1622,22 +2180,40 @@ } private Map.Entry, Map>>> declareInputMethodsInThisAndMainComponents(ResourceNode resourceNode, TypeDeclaration component, - TypeDeclaration parentComponent, TypeDeclaration mainComponent, DataTransferModel model, ILanguageSpecific langSpec) { + TypeDeclaration parentComponent, TypeDeclaration mainComponent, TypeDeclaration rootComponent, DataTransferModel model, Map priorMemberForInputChannel, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { // Declare input methods. String resName = resourceNode.getResourceName(); String resComponentName = langSpec.toComponentName(resName); List constructorStatements = new ArrayList<>(); Map>> inputStatements = new HashMap<>(); for (Channel ch: model.getInputChannels()) { + for (ChannelMember cm : ((DataTransferChannel) ch).getOutputChannelMembers()) { + if (!cm.isOutside()) { + if (priorMemberForInputChannel.get(ch) == null) { + priorMemberForInputChannel.put(ch, cm); // The receiver of the input event when multiple output resources are defined for the channel. + } + } + } for (ChannelMember out: ((DataTransferChannel) ch).getOutputChannelMembers()) { if (resourceNode.getInSideResources().contains(out.getResource())) { Expression message = out.getStateTransition().getMessageExpression(); MethodDeclaration input = null; - MethodDeclaration inputAccessor = null; + MethodDeclaration mainInputAccessor = null; + MethodDeclaration rootInputAccessor = null; if (message instanceof Term) { // Declare an input method in this component. ArrayList resInputParams = new ArrayList<>(); ArrayList mainInputParams = new ArrayList<>(); + ArrayList rootInputParams = new ArrayList<>(); + String resourcePath = null; + if (!platformSpec.isMonolithic()) { + resourcePath = getInputMethodResourcePathAndPathParams(out.getResource(), rootInputParams, platformSpec, langSpec); // Path parameters for the input REST API. + if (resourcePath.indexOf('/') > 0) { + resourcePath = resourcePath.substring(resourcePath.indexOf('/')); + } else { + resourcePath = ""; + } + } // The path parameters are not to be passed to the input method of each resource (resInputParams) // because they are always equal to either channel selectors or message parameters. @@ -1696,58 +2272,83 @@ if (!bExists) { mainInputParams.add(langSpec.newVariableDeclaration(var.getType(), var.getName())); } - } - } - String inputMethodName = ((Term) message).getSymbol().getImplName(); - if (((DataTransferChannel) ch).getOutputChannelMembers().size() > 1) { - inputMethodName += _for + getComponentName(out.getResource().getResourceHierarchy(), langSpec); - } - if (component != null) { - // A component is created for this resource. - for (MethodDeclaration method: component.getMethods()) { - if (method.getName().equals(inputMethodName)) { - input = method; - break; + if (!platformSpec.isMonolithic() && !resourcePath.contains("{" + var.getName()+ "}")) { + VariableDeclaration param = langSpec.newVariableDeclaration(var.getType(), var.getName()); + ((RestApiSpecific) platformSpec).addFormParamAnnotation(param, var.getName()); + rootInputParams.add(param); } } - if (input == null) { - input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); - component.addMethod(input); + } + if (platformSpec.isMonolithic() + || (resourceNode.getResourceHierarchy().getParent() != null && resourceNode.getResourceHierarchy().getParent().getParent() != null)) { + String inputMethodName = ((Term) message).getSymbol().getImplName(); + if (((DataTransferChannel) ch).getOutputChannelMembers().size() > 1) { + inputMethodName += _for + getComponentName(out.getResource().getResourceHierarchy(), langSpec); } - } else if (parentComponent != null) { - // No component is created for this resource. - for (MethodDeclaration method: parentComponent.getMethods()) { - if (method.getName().equals(inputMethodName)) { - input = method; - break; + if (component != null) { + // A component is created for this resource. + for (MethodDeclaration method: component.getMethods()) { + if (method.getName().equals(inputMethodName)) { + input = method; + break; + } } - } - if (input == null) { - input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); - parentComponent.addMethod(input); + if (input == null) { + input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); + component.addMethod(input); + } + } else if (parentComponent != null) { + // No component is created for this resource. + for (MethodDeclaration method: parentComponent.getMethods()) { + if (method.getName().equals(inputMethodName)) { + input = method; + break; + } + } + if (input == null) { + input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); + parentComponent.addMethod(input); + } } } - // Declare the accessor in the main component to call the input method. - String messageSymbol = ((Term) message).getSymbol().getImplName(); - inputAccessor = getMethod(mainComponent, messageSymbol); - if (inputAccessor == null) { - inputAccessor = langSpec.newMethodDeclaration(messageSymbol, false, null, mainInputParams); - mainComponent.addMethod(inputAccessor); - } else { - // Add type to a parameter without type. - if (inputAccessor.getParameters() != null) { - for (VariableDeclaration param: inputAccessor.getParameters()) { - if (param.getType() == null) { - for (VariableDeclaration p: mainInputParams) { - if (param.getName().equals(p.getName()) && p.getType() != null) { - param.setType(p.getType()); + // Declare the accessor in the main component to call the input method. (for monolithic application) + if (platformSpec.hasMain()) { + String messageSymbol = ((Term) message).getSymbol().getImplName(); + mainInputAccessor = getMethod(mainComponent, messageSymbol); + if (mainInputAccessor == null) { + mainInputAccessor = langSpec.newMethodDeclaration(messageSymbol, false, null, mainInputParams); + mainComponent.addMethod(mainInputAccessor); + } else { + // Add type to a parameter without type. + if (mainInputAccessor.getParameters() != null) { + for (VariableDeclaration param: mainInputAccessor.getParameters()) { + if (param.getType() == null) { + for (VariableDeclaration p: mainInputParams) { + if (param.getName().equals(p.getName()) && p.getType() != null) { + param.setType(p.getType()); + } } } } } } } + + // For the root resource. (for REST API) + if (!platformSpec.isMonolithic()) { + if (priorMemberForInputChannel.get(ch) == null || out == priorMemberForInputChannel.get(ch)) { + // If out is the receiver of the input event. + priorMemberForInputChannel.put(ch, out); + String messageSymbol = ((Term) message).getSymbol().getImplName(); + rootInputAccessor = declareInputAccessorInTheRootResource(messageSymbol, rootInputParams, out, resourcePath, + rootComponent, platformSpec, langSpec); + if (input == null) { + input = rootInputAccessor; + rootInputAccessor = null; + } + } + } } else if (message instanceof Variable) { // Declare an input method in this component. ArrayList resInputParams = new ArrayList<>(); @@ -1778,72 +2379,103 @@ v++; } } - String inputMethodName = ((Variable) message).getName(); - if (((DataTransferChannel) ch).getOutputChannelMembers().size() > 1) { - inputMethodName += _for + getComponentName(out.getResource().getResourceHierarchy(), langSpec); - } - if (component != null) { - // A component is created for this resource. - for (MethodDeclaration method: component.getMethods()) { - if (method.getName().equals(inputMethodName)) { - input = method; - break; - } + if (platformSpec.isMonolithic() + || (resourceNode.getResourceHierarchy().getParent() != null && resourceNode.getResourceHierarchy().getParent().getParent() != null)) { + String inputMethodName = ((Variable) message).getName(); + if (((DataTransferChannel) ch).getOutputChannelMembers().size() > 1) { + inputMethodName += _for + getComponentName(out.getResource().getResourceHierarchy(), langSpec); } - if (input == null) { - if (resInputParams.size() == 0) { - input = langSpec.newMethodDeclaration(inputMethodName, null); - } else { - input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); + if (component != null) { + // A component is created for this resource. + for (MethodDeclaration method: component.getMethods()) { + if (method.getName().equals(inputMethodName)) { + input = method; + break; + } } - component.addMethod(input); - } - } else if (parentComponent != null) { - // No component is created for this resource. - for (MethodDeclaration method: parentComponent.getMethods()) { - if (method.getName().equals(inputMethodName)) { - input = method; - break; + if (input == null) { + if (resInputParams.size() == 0) { + input = langSpec.newMethodDeclaration(inputMethodName, null); + } else { + input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); + } + component.addMethod(input); } - } - if (input == null) { - if (resInputParams.size() == 0) { - input = langSpec.newMethodDeclaration(inputMethodName, null); - } else { - input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); + } else if (parentComponent != null) { + // No component is created for this resource. + for (MethodDeclaration method: parentComponent.getMethods()) { + if (method.getName().equals(inputMethodName)) { + input = method; + break; + } } - parentComponent.addMethod(input); + if (input == null) { + if (resInputParams.size() == 0) { + input = langSpec.newMethodDeclaration(inputMethodName, null); + } else { + input = langSpec.newMethodDeclaration(inputMethodName, false, null, resInputParams); + } + parentComponent.addMethod(input); + } } } - // Declare the accessor in the main component to call the input method. - String messageSymbol = ((Variable) message).getName(); - inputAccessor = getMethod(mainComponent, messageSymbol); - if (inputAccessor == null) { - if (mainInputParams.size() == 0) { - inputAccessor = langSpec.newMethodDeclaration(messageSymbol, null); - } else { - inputAccessor = langSpec.newMethodDeclaration(messageSymbol, false, null, mainInputParams); + // Declare the accessor in the main component to call the input method. (for monolithic application) + if (platformSpec.hasMain()) { + String messageSymbol = ((Variable) message).getName(); + mainInputAccessor = getMethod(mainComponent, messageSymbol, mainInputParams); + if (mainInputAccessor == null) { + if (mainInputParams.size() == 0) { + mainInputAccessor = langSpec.newMethodDeclaration(messageSymbol, null); + } else { + mainInputAccessor = langSpec.newMethodDeclaration(messageSymbol, false, null, mainInputParams); + } + mainComponent.addMethod(mainInputAccessor); } - mainComponent.addMethod(inputAccessor); + } + + // For the root resource. (for REST API) + if (!platformSpec.isMonolithic()) { + if (priorMemberForInputChannel.get(ch) == null || out == priorMemberForInputChannel.get(ch)) { + // If out is the receiver of the input event. + priorMemberForInputChannel.put(ch, out); + ArrayList rootInputParams = new ArrayList<>(); + String resourcePath = getGetterResourcePathAndPathParams(out.getResource(), rootInputParams, platformSpec, langSpec); + if (resourcePath.indexOf('/') > 0) { + resourcePath = resourcePath.substring(resourcePath.indexOf('/')); + } else { + resourcePath = ""; + } + String messageSymbol = ((Variable) message).getName(); + rootInputAccessor = declareInputAccessorInTheRootResource(messageSymbol, rootInputParams, out, resourcePath, + rootComponent, platformSpec, langSpec); + if (input == null) { + input = rootInputAccessor; + rootInputAccessor = null; + } + } } } // Add an invocation to the accessor method. - if (inputAccessor != null) { - for (ChannelMember rc: ((DataTransferChannel) ch).getReferenceChannelMembers()) { - // For each reference channel member, get the current state of the reference side resource by pull data transfer. - ResourcePath ref = rc.getResource(); - if (!out.getResource().equals(ref)) { - String refVarName = ref.getLeafResourceName(); - Expression refGetter = getPullAccessor().getDirectStateAccessorFor(ref, null); - String[] sideEffects = new String[] {""}; - String refExp = refGetter.toImplementation(sideEffects); - String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); - inputAccessor.addFirstStatement(sideEffects[0] + refTypeName + " " + refVarName + " = " + refExp + ";"); + if (mainInputAccessor != null) { + if (platformSpec.hasMain()) { + // For an application with a main component, the reference resource is accessed from the main component. + for (ChannelMember rc: ((DataTransferChannel) ch).getReferenceChannelMembers()) { + // For each reference channel member, get the current state of the reference resource by pull data transfer. + ResourcePath ref = rc.getResource(); + if (!out.getResource().equals(ref)) { + String refVarName = ref.getLeafResourceName(); + Expression refGetter = getPullAccessor(platformSpec).getDirectStateAccessorFor(ref, null); + String[] sideEffects = new String[] {""}; + String refExp = refGetter.toImplementation(sideEffects); + String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); + mainInputAccessor.addFirstStatement(sideEffects[0] + langSpec.getVariableDeclaration(refTypeName, refVarName) + + langSpec.getAssignment() + refExp + langSpec.getStatementDelimiter()); + } } } - Expression resExp = getPullAccessor().getDirectStateAccessorFor(out.getResource(), null); + Expression resExp = getPullAccessor(platformSpec).getDirectStateAccessorFor(out.getResource(), null); List args = new ArrayList<>(); if (resExp instanceof Term) { // to access the parent @@ -1882,13 +2514,43 @@ } } } - inputAccessor.addStatement(langSpec.getMethodInvocation(resourceAccess, input.getName(), args) + langSpec.getStatementDelimiter()); + mainInputAccessor.addStatement(langSpec.getMethodInvocation(resourceAccess, input.getName(), args) + langSpec.getStatementDelimiter()); } if (input != null) { // Add a statement to update the state field to the input method. try { - Expression updateExp = ((DataTransferChannel) ch).deriveUpdateExpressionOf(out, getRefAccessor()).getKey(); + if (!platformSpec.hasMain()) { + // For an application with no main component, the reference resource is accessed from each resource. + for (ChannelMember rc: ((DataTransferChannel) ch).getReferenceChannelMembers()) { + // For each reference channel member, get the current state of the reference side resource by pull data transfer. + ResourcePath ref = rc.getResource(); + if (!out.getResource().equals(ref)) { + String refResourceName = ref.getLeafResourceName(); + Type refResourceType = ref.getResourceStateType(); + String[] sideEffects = new String[] {""}; + if (!platformSpec.isMonolithic() && rc.isOutside()) { + List pathParams = new ArrayList<>(); + for (Expression pathExp: ref.getPathParams()) { + pathParams.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); + } + generatePullDataTransfer(input, refResourceName, ref.getResourceHierarchy().toResourcePath(pathParams), refResourceType, true, platformSpec, langSpec); + } else { + ResourcePath dstRes = out.getResource(); + if (!generatesComponent(dstRes.getResourceHierarchy())) { + dstRes = dstRes.getParent(); + } + Expression refGetter = getPullAccessor(platformSpec).getDirectStateAccessorFor(ref, dstRes); + String refExp = refGetter.toImplementation(sideEffects); + String refTypeName = refResourceType.getInterfaceTypeName(); + input.addFirstStatement(sideEffects[0] + langSpec.getVariableDeclaration(refTypeName, refResourceName) + + langSpec.getAssignment() + refExp + langSpec.getStatementDelimiter()); + } + } + } + } + + Expression updateExp = ((DataTransferChannel) ch).deriveUpdateExpressionOf(out, getRefAccessor(platformSpec)).getKey(); // Replace Json constructor with a constructor of a descendant resource. ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); if (outRes.getChildren().size() == 1 && outRes.getChildren().iterator().next().getNumParameters() > 0) { @@ -1955,12 +2617,49 @@ } } } + if (rootInputAccessor != null) { + // In the root resource + // The expression of the receiver (resource) of the input method. + ResourcePath outResPath = new ResourcePath(out.getResource()); + for (int i = 0; i < outResPath.getPathParams().size(); i++) { + Parameter pathParam = new Parameter(rootInputAccessor.getParameters().get(i).getName()); + outResPath.replacePathParam(i, pathParam, null); + } + Expression resExp = getPullAccessor(platformSpec).getDirectStateAccessorFor(outResPath, outResPath.getRoot()); + List args = new ArrayList<>(); + if (resExp instanceof Term) { + // to access the parent + if (((Term) resExp).getChildren().size() > 1 && ((Term) resExp).getChild(1) instanceof Variable) { + args.add(((Variable)((Term) resExp).getChild(1)).getName()); + } + resExp = ((Term) resExp).getChild(0); + } + String resourceAccess = resExp.toImplementation(new String[] {""}); + // Values of channel parameters. + for (Selector selector: ch.getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable selVar = (Variable) selector.getExpression(); + args.add(selVar.getName()); + } + } + // Values of message parameters. + if (message instanceof Term) { + for (Variable mesVar: message.getVariables().values()) { + args.add(mesVar.getName()); + } + } + rootInputAccessor.addStatement(langSpec.getMethodInvocation(resourceAccess, input.getName(), args) + langSpec.getStatementDelimiter()); + if (input != null && input.getThrows() != null && ((RestApiSpecific) platformSpec).hasJsonException(input)) { + ((RestApiSpecific) platformSpec).addJsonException(rootInputAccessor); + } + } } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage | UnificationFailed | ValueUndefined e) { e.printStackTrace(); } // Add an invocation to an update method (for a chain of update method invocations). + boolean hasUpdateMethodinvoked = false; for (Edge resToCh: resourceNode.getOutEdges()) { DataFlowEdge dOut = (DataFlowEdge) resToCh; ChannelNode directDstChNode = (ChannelNode) resToCh.getDestination(); @@ -2017,6 +2716,23 @@ } if ((((PushPullAttribute) dOut.getAttribute()).getSelectedOption() == PushPullValue.PUSH && !outsideInputResource2) || outsideOutputResource2) { // PUSH transfer + + // Calculate in-degree (PUSH transfer) of the destination resource. + Set inEdges = new HashSet<>(); + inEdges.addAll(directDstChNode.getInEdges()); + for (ChannelNode ancestorSrc: ancestorDstChannels) { + inEdges.addAll(ancestorSrc.getInEdges()); + } + for (ChannelNode descendantSrc: descendantDstChannels) { + inEdges.addAll(descendantSrc.getInEdges()); + } + int inDegree = 0; + for (Edge resToCh2: inEdges) { + DataFlowEdge df =(DataFlowEdge) resToCh2; + if (((PushPullAttribute) df.getAttribute()).getSelectedOption() == PushPullValue.PUSH) { + inDegree++; + } + } boolean addForStatement = false; String forVarName = null; if (descendantDstChannels.contains(chNode2)) { @@ -2055,17 +2771,41 @@ insideResPath = insideResPath.getParent(); } insideResPath = insideResPath.getParent(); - String parent = getPullAccessor().getDirectStateAccessorFor(insideResPath, resourceNode.getPrimaryResourcePath()).toImplementation(new String[] {}); if (insideResPath != null) { + String parent = null; + if (platformSpec.isMonolithic() + || insideResPath.getCommonPrefix(resourceNode.getOutSideResource(directDstCh)) != null + || !platformSpec.isDifferentTreesAsDifferentServices()) { + if (!platformSpec.isMonolithic() && generatesComponent(insideResPath.getResourceHierarchy())) { + Expression getter = getPullAccessor(platformSpec).getDirectStateAccessorFor(insideResPath, resourceNode.getOutSideResource(directDstCh)); + Term valueGetter = new Term(new Symbol(getterOfResourceState, 1, Symbol.Type.METHOD)); + valueGetter.addChild(getter); + parent = valueGetter.toImplementation(new String[] {}); + } else { + parent = getPullAccessor(platformSpec).getDirectStateAccessorFor(insideResPath, resourceNode.getOutSideResource(directDstCh)).toImplementation(new String[] {}); + } + } else { + // for REST API + parent = langSpec.toVariableName(getComponentName(insideResPath.getResourceHierarchy(), langSpec)); + } if (selType.equals(DataConstraintModel.typeInt)) { // make a for loop (for a list) for broadcasting. - input.addStatement(langSpec.getForStatement(forVarName, parent)); + input.addStatement(langSpec.getForStatementForList(forVarName, parent)); addForStatement = true; } else if (selType.equals(DataConstraintModel.typeString)) { // make a for loop (for a map) for broadcasting. - input.addStatement(langSpec.getForStatement(forVarName, DataConstraintModel.typeString.getInterfaceTypeName(), parent)); + input.addStatement(langSpec.getForStatementForMap(forVarName, DataConstraintModel.typeString.getInterfaceTypeName(), parent)); addForStatement = true; } + if (!platformSpec.isMonolithic() + && insideResPath.getCommonPrefix(resourceNode.getOutSideResource(directDstCh)) == null + && platformSpec.isDifferentTreesAsDifferentServices()) { + // for REST API + Type parentResType = insideResPath.getResourceStateType(); + String parentResName = langSpec.toVariableName(getComponentName(insideResPath.getResourceHierarchy(), langSpec)); + String parentResPath = insideResPath.toString().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); + generatePullDataTransfer(input, parentResName, parentResPath, parentResType, true, platformSpec, langSpec); + } } } else if (selExp instanceof Term) { // not supported. @@ -2073,7 +2813,7 @@ } } // Get the value of reference member to call the update method. - List params = new ArrayList<>(); + List>> refParams = new ArrayList<>(); Map> referredResources = new HashMap<>(); Set referredSet = referredResources.get(input); for (ChannelMember rc: ch2.getReferenceChannelMembers()) { @@ -2090,70 +2830,107 @@ if (!generatesComponent(srcRes.getResourceHierarchy())) { srcRes = srcRes.getParent(); } - Expression refGetter = getPullAccessor().getDirectStateAccessorFor(ref, srcRes); + Expression refGetter = getPullAccessor(platformSpec).getDirectStateAccessorFor(ref, srcRes); String[] sideEffects = new String[] {""}; String refExp = refGetter.toImplementation(sideEffects); String refTypeName = ref.getResourceStateType().getInterfaceTypeName(); input.addStatement(sideEffects[0] + langSpec.getVariableDeclaration(refTypeName, refVarName) + langSpec.getAssignment() + refExp + langSpec.getStatementDelimiter()); } - params.add(refVarName); + refParams.add(new AbstractMap.SimpleEntry<>(ref.getResourceStateType(), + new AbstractMap.SimpleEntry<>(refVarName, + refVarName))); } } - // Update fields to refer to outside resources. - try { - Map>> resourcePaths = ch2.fillOutsideResourcePaths(out2, getPullAccessor()); - if (resourcePaths != null && resourcePaths.size() > 0) { - for (ChannelMember outsideMember: resourcePaths.keySet()) { - ResourcePath outsidePath = resourcePaths.get(outsideMember).getKey(); - if (!generatesComponent(outsidePath.getResourceHierarchy())) { - outsidePath = outsidePath.getParent(); - } - String outsideResName = langSpec.toVariableName(getComponentName(outsidePath.getResourceHierarchy(), langSpec)); - Expression outsideExp = getPullAccessor().getDirectStateAccessorFor(outsidePath, null); - if (generatesComponent(outsidePath.getResourceHierarchy())) { - outsideExp = ((Term) outsideExp).getChild(0); - } - if (outsideExp instanceof Field) { - outsideExp = new Variable(((Field) outsideExp).getSymbol().getName(), ((Field) outsideExp).getType()); - } else if (outsideExp instanceof Term) { - for (Entry fieldEnt: ((Term) outsideExp).getSubTerms(Field.class).entrySet()) { - Position pos = fieldEnt.getKey(); - Field field = fieldEnt.getValue(); - Variable var = new Variable(field.getSymbol().getName(), field.getType()); - ((Term) outsideExp).replaceSubTerm(pos, var); + List>> pathParams = new ArrayList<>(); + if (platformSpec.isMonolithic()) { + // Update fields to refer to outside resources. + ResourcePath filledOutsideResourcePath = null; + try { + Map>> resourcePaths = ch2.fillOutsideResourcePaths(out2, getPullAccessor(platformSpec)); + if (resourcePaths != null && resourcePaths.size() > 0) { + for (ChannelMember outsideMember: resourcePaths.keySet()) { + ResourcePath outsidePath = resourcePaths.get(outsideMember).getKey(); + if (out2.equals(outsideMember)) { + filledOutsideResourcePath = outsidePath; } + if (!generatesComponent(outsidePath.getResourceHierarchy())) { + outsidePath = outsidePath.getParent(); + } + String outsideResName = langSpec.toVariableName(getComponentName(outsidePath.getResourceHierarchy(), langSpec)); + Expression outsideExp = getPullAccessor(platformSpec).getDirectStateAccessorFor(outsidePath, null); + if (generatesComponent(outsidePath.getResourceHierarchy())) { + outsideExp = ((Term) outsideExp).getChild(0); + } + if (outsideExp instanceof Field) { + outsideExp = new Variable(((Field) outsideExp).getSymbol().getName(), ((Field) outsideExp).getType()); + } else if (outsideExp instanceof Term) { + for (Entry fieldEnt: ((Term) outsideExp).getSubTerms(Field.class).entrySet()) { + Position pos = fieldEnt.getKey(); + Field field = fieldEnt.getValue(); + Variable var = new Variable(field.getSymbol().getName(), field.getType()); + ((Term) outsideExp).replaceSubTerm(pos, var); + } + } + String[] sideEffects = new String[] {""}; + String outsideAccessor = outsideExp.toImplementation(sideEffects); + input.addStatement(langSpec.getFieldAccessor(outsideResName) + langSpec.getAssignment() + outsideAccessor + langSpec.getStatementDelimiter()); // change the reference field. } - String[] sideEffects = new String[] {""}; - String outsideAccessor = outsideExp.toImplementation(sideEffects); - input.addStatement(langSpec.getFieldAccessor(outsideResName) + langSpec.getAssignment() + outsideAccessor + langSpec.getStatementDelimiter()); // change the reference field. + } + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined e) { + e.printStackTrace(); + } + // Values of path parameters to call the update method. + if (filledOutsideResourcePath == null) { + filledOutsideResourcePath = out2.getResource(); + } + for (Expression pathParam: filledOutsideResourcePath.getPathParams()) { + if (pathParam instanceof Variable) { + Variable pathVar = (Variable) pathParam; + pathParams.add(new AbstractMap.SimpleEntry<>(pathVar.getType(), + new AbstractMap.SimpleEntry<>(pathVar.getName(), + pathVar.getName()))); + } else if (pathParam instanceof Constant) { + Constant pathVar = (Constant) pathParam; + pathParams.add(new AbstractMap.SimpleEntry<>(pathVar.getType(), + new AbstractMap.SimpleEntry<>(pathVar.getSymbol().getName(), + pathVar.getSymbol().getName()))); } } - } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork - | InvalidMessage | UnificationFailed | ValueUndefined e) { - e.printStackTrace(); - } - // Values of path parameters to call the update method. - for (Expression pathParam: out2.getResource().getPathParams()) { - if (pathParam instanceof Variable) { - Variable pathVar = (Variable) pathParam; - params.add(pathVar.getName()); + } else { + // Values of path parameters to call the update method. + for (Expression pathParam: out2.getResource().getPathParams()) { + if (pathParam instanceof Variable) { + Variable pathVar = (Variable) pathParam; + pathParams.add(new AbstractMap.SimpleEntry<>(pathVar.getType(), + new AbstractMap.SimpleEntry<>(pathVar.getName(), + pathVar.getName()))); + } } } // Values of channel parameters to call the update method. + List>> params = new ArrayList<>(); for (Selector selector: ch2.getAllSelectors()) { if (selector.getExpression() instanceof Variable) { Variable selVar = (Variable) selector.getExpression(); - params.add(selVar.getName()); + params.add(new AbstractMap.SimpleEntry<>(selVar.getType(), + new AbstractMap.SimpleEntry<>(selVar.getName(), + selVar.getName()))); } } // Value of the source side (input side) resource to call the update method. ResourceHierarchy srcRes = resourceNode.getResourceHierarchy(); if (generatesComponent(srcRes)) { - params.add(langSpec.getFieldAccessor(fieldOfResourceState)); + params.add(new AbstractMap.SimpleEntry<>(srcRes.getResourceStateType(), + new AbstractMap.SimpleEntry<>(langSpec.toVariableName(srcRes.getResourceName()), + langSpec.getFieldAccessor(fieldOfResourceState)))); } else { - params.add(langSpec.getFieldAccessor(langSpec.toVariableName(srcRes.getResourceName()))); + params.add(new AbstractMap.SimpleEntry<>(srcRes.getResourceStateType(), + new AbstractMap.SimpleEntry<>(langSpec.toVariableName(srcRes.getResourceName()), + langSpec.getFieldAccessor(langSpec.toVariableName(srcRes.getResourceName()))))); srcRes = srcRes.getParent(); } + params.addAll(refParams); // Call the update method. String updateMethodName = null; ResourceHierarchy dstRes = dstNode.getResourceHierarchy(); @@ -2164,19 +2941,87 @@ updateMethodName = updateMethodPrefix + from + resComponentName; } String dstCompName = langSpec.toVariableName(getComponentName(dstRes, langSpec)); - if (!outsideOutputResource2) { - // The destination resource is not outside. - if (srcRes != dstRes) { - input.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstCompName), updateMethodName, params) - + langSpec.getStatementDelimiter()); // this.dst.updateDstFromSrc(value, refParams); + if (outsideOutputResource2 + || (!platformSpec.isMonolithic() && in.getResource().getCommonPrefix(out2.getResource()) == null && platformSpec.isDifferentTreesAsDifferentServices())) { + // Inter-servces + if (!platformSpec.isMonolithic()) { + // REST API + RestApiSpecific restApiSpec = (RestApiSpecific) platformSpec; + String httpMethod = null; + if (out2.getStateTransition().isRightUnary()) { + httpMethod = "put"; + } else { + httpMethod = "post"; + } + String[] sideEffects = new String[] {""}; + List pathParamsUrl = new ArrayList<>(); + for (Expression pathExp: out2.getResource().getPathParams()) { + pathParamsUrl.add("\" + " + pathExp.toImplementation(sideEffects) + " + \""); + } + String resName2 = langSpec.toVariableName(resComponentName); + if (inDegree <= 1) { + resName2 = null; + } + Map>> filledPaths = null; + try { + filledPaths = ch2.fillOutsideResourcePaths(out2, getPushAccessor(platformSpec)); + } catch (ParameterizedIdentifierIsFutureWork + | ResolvingMultipleDefinitionIsFutureWork | InvalidMessage + | UnificationFailed | ValueUndefined e) { + e.printStackTrace(); + } + String dstPath = null; + if (filledPaths != null && filledPaths.get(out2) != null) { + ResourcePath filledDstPath = filledPaths.get(out2).getKey(); + dstPath = filledDstPath.toString().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); + } else { + dstPath = dstRes.toResourcePath(pathParamsUrl); + } + // Call the update method. + if (!hasUpdateMethodinvoked) { + // The first call to an update method in this method + input.addStatement(restApiSpec.getHttpMethodParamsConstructionStatement(srcRes.getResourceName(), params, true)); + input.addStatement(langSpec.getVariableDeclaration(DataConstraintModel.typeString.getInterfaceTypeName(), "result") + + langSpec.getAssignment() + restApiSpec.getHttpMethodCallStatement(restApiSpec.getBaseURL(), dstPath, resName2, httpMethod)); + hasUpdateMethodinvoked = true; + if (component != null && !((RestApiSpecific) platformSpec).hasHttpClientFieldDeclaration(component)) { + // Declare a client field to connect to the destination resource of push transfer. + ((RestApiSpecific) platformSpec).addHttpClientFieldDeclaration(component); + } + } else { + // After the second time of call to update methods in this method + input.addStatement(restApiSpec.getHttpMethodParamsConstructionStatement(srcRes.getResourceName(), params, false)); + input.addStatement("result" + langSpec.getAssignment() + restApiSpec.getHttpMethodCallStatement(restApiSpec.getBaseURL(), dstPath, resName2, httpMethod)); + } } else { - input.addStatement(langSpec.getMethodInvocation(updateMethodName, params) - + langSpec.getStatementDelimiter()); // this.updateDstFromSrc(value, refParams); + // Use the reference field to refer to outside destination resource. + List args = new ArrayList<>(); + for (Map.Entry> paramEnt: pathParams) { + args.add(paramEnt.getValue().getValue()); + } + for (Map.Entry> paramEnt: params) { + args.add(paramEnt.getValue().getValue()); + } + input.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstCompName), updateMethodName, args) + + langSpec.getStatementDelimiter()); // this.dst.updateDstFromSrc(value, refParams); } } else { - // Use the reference field to refer to outside destination resource. - input.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstCompName), updateMethodName, params) - + langSpec.getStatementDelimiter()); // this.dst.updateDstFromSrc(value, refParams); + // Intra-service + // The destination resource is not outside. + List args = new ArrayList<>(); + for (Map.Entry> paramEnt: pathParams) { + args.add(paramEnt.getValue().getValue()); + } + for (Map.Entry> paramEnt: params) { + args.add(paramEnt.getValue().getValue()); + } + if (srcRes != dstRes) { + input.addStatement(langSpec.getMethodInvocation(langSpec.getFieldAccessor(dstCompName), updateMethodName, args) + + langSpec.getStatementDelimiter()); // this.dst.updateDstFromSrc(value, refParams); + } else { + input.addStatement(langSpec.getMethodInvocation(updateMethodName, args) + + langSpec.getStatementDelimiter()); // this.updateDstFromSrc(value, refParams); + } } if (addForStatement) { // Close the for loop. @@ -2184,48 +3029,53 @@ } } } - if (outsideInputMembers2.size() > 0) { - if (!generatesComponent(resourceNode.getResourceHierarchy())) { - ResourcePath srcRes2 = resourceNode.getOutSideResource(directDstCh); - for (ChannelMember out2: directDstCh.getOutputChannelMembers()) { - if (!generatesComponent(out2.getResource().getResourceHierarchy())) { - ResourcePath dstRes2 = out2.getResource(); - if (srcRes2.getParent().equals(dstRes2.getParent())) { - Map>> resourcePaths = null; - try { - resourcePaths = directDstCh.fillOutsideResourcePaths(out2, getPullAccessor()); - if (resourcePaths != null && resourcePaths.size() > 0) { - for (ChannelMember outsideMember: outsideInputMembers2) { - for (ChannelMember dependedMember: resourcePaths.get(outsideMember).getValue()) { - if (dependedMember.getResource().equals(srcRes2)) { - // An outside input resource path depends on srcRes. - ResourcePath outsidePath = resourcePaths.get(outsideMember).getKey(); - if (!generatesComponent(outsidePath.getResourceHierarchy())) { - outsidePath = outsidePath.getParent(); - } - String outsideResName = langSpec.toVariableName(getComponentName(outsidePath.getResourceHierarchy(), langSpec)); - Expression outsideExp = getPullAccessor().getDirectStateAccessorFor(outsidePath, null); - if (generatesComponent(outsidePath.getResourceHierarchy())) { - outsideExp = ((Term) outsideExp).getChild(0); - } - String[] sideEffects = new String[] {""}; - String outsideAccessor = outsideExp.toImplementation(sideEffects); - input.addStatement(langSpec.getFieldAccessor(outsideResName) + langSpec.getAssignment() + outsideAccessor + langSpec.getStatementDelimiter()); // change the reference field. - // Update constructor. - String initializingStatement = langSpec.getFieldAccessor(outsideResName) + langSpec.getAssignment() + outsideAccessor + langSpec.getStatementDelimiter(); - if (component != null) { - MethodDeclaration constructor = getConstructor(component); - constructor.addStatement(initializingStatement); // initialize the reference field. - } else { - constructorStatements.add(initializingStatement); // initialize the reference field. + + // Update and initialize a field to refer to an outside input resource for PULL transfer. + if (platformSpec.isMonolithic()) { + // For a monolithic application. + if (outsideInputMembers2.size() > 0) { + if (!generatesComponent(resourceNode.getResourceHierarchy())) { + ResourcePath srcRes2 = resourceNode.getOutSideResource(directDstCh); + for (ChannelMember out2: directDstCh.getOutputChannelMembers()) { + if (!generatesComponent(out2.getResource().getResourceHierarchy())) { + ResourcePath dstRes2 = out2.getResource(); + if (srcRes2.getParent().equals(dstRes2.getParent())) { + Map>> resourcePaths = null; + try { + resourcePaths = directDstCh.fillOutsideResourcePaths(out2, getPullAccessor(platformSpec)); + if (resourcePaths != null && resourcePaths.size() > 0) { + for (ChannelMember outsideMember: outsideInputMembers2) { + for (ChannelMember dependedMember: resourcePaths.get(outsideMember).getValue()) { + if (dependedMember.getResource().equals(srcRes2)) { + // An outside input resource path depends on srcRes. + ResourcePath outsidePath = resourcePaths.get(outsideMember).getKey(); + if (!generatesComponent(outsidePath.getResourceHierarchy())) { + outsidePath = outsidePath.getParent(); + } + String outsideResName = langSpec.toVariableName(getComponentName(outsidePath.getResourceHierarchy(), langSpec)); + Expression outsideExp = getPullAccessor(platformSpec).getDirectStateAccessorFor(outsidePath, null); + if (generatesComponent(outsidePath.getResourceHierarchy())) { + outsideExp = ((Term) outsideExp).getChild(0); + } + String[] sideEffects = new String[] {""}; + String outsideAccessor = outsideExp.toImplementation(sideEffects); + input.addStatement(langSpec.getFieldAccessor(outsideResName) + langSpec.getAssignment() + outsideAccessor + langSpec.getStatementDelimiter()); // change the reference field. + // Update constructor. + String initializingStatement = langSpec.getFieldAccessor(outsideResName) + langSpec.getAssignment() + outsideAccessor + langSpec.getStatementDelimiter(); + if (component != null) { + MethodDeclaration constructor = getConstructor(component); + constructor.addStatement(initializingStatement); // initialize the reference field. + } else { + constructorStatements.add(initializingStatement); // initialize the reference field. + } } } } } + } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork + | InvalidMessage | UnificationFailed | ValueUndefined e) { + e.printStackTrace(); } - } catch (ParameterizedIdentifierIsFutureWork | ResolvingMultipleDefinitionIsFutureWork - | InvalidMessage | UnificationFailed | ValueUndefined e) { - e.printStackTrace(); } } } @@ -2239,4 +3089,139 @@ } return new AbstractMap.SimpleEntry<>(constructorStatements, inputStatements); } + + protected void declareGetterAccessorInTheRootResource(ResourceNode resourceNode, TypeDeclaration rootComponent, + IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + if (resourceNode.getResourceHierarchy().getParent() != null) { + // For a non-root resource + MethodDeclaration getterAccessor = null; + List mainGetterParams = new ArrayList<>(); + String resourcePath = getGetterResourcePathAndPathParams(resourceNode.getPrimaryResourcePath(), mainGetterParams, platformSpec, langSpec); + if (resourcePath.indexOf('/') > 0) { + resourcePath = resourcePath.substring(resourcePath.indexOf('/')); + } else { + resourcePath = ""; + } + if (mainGetterParams.size() > 0) { + getterAccessor = langSpec.newMethodDeclaration(getterPrefix + getComponentName(resourceNode.getResourceHierarchy(), langSpec) + methoNameOfResourceState, + false, + getImplStateType(resourceNode.getResourceHierarchy(), langSpec), + mainGetterParams); + } else { + getterAccessor = langSpec.newMethodDeclaration(getterPrefix + getComponentName(resourceNode.getResourceHierarchy(), langSpec) + methoNameOfResourceState, + getImplStateType(resourceNode.getResourceHierarchy(), langSpec)); + } + getterAccessor.setBody(new Block()); + ResourcePath resPath = new ResourcePath(resourceNode.getPrimaryResourcePath()); + for (int i = 0; i < mainGetterParams.size(); i++) { + Parameter pathParam = new Parameter(mainGetterParams.get(i).getName()); + resPath.replacePathParam(i, pathParam, null); + } + Expression getState = getPullAccessor(platformSpec).getDirectStateAccessorFor(resPath, resPath.getRoot()); + getterAccessor.getBody().addStatement(langSpec.getReturnStatement(getState.toImplementation(new String[] {null})) + langSpec.getStatementDelimiter()); + if (!platformSpec.isMonolithic()) { + ((RestApiSpecific) platformSpec).addGetAnnotations(getterAccessor); + if (resourcePath.length() > 0) { + ((RestApiSpecific) platformSpec).addPathAnnotation(getterAccessor, resourcePath); + } + } + rootComponent.addMethod(getterAccessor); + } + } + + protected void declareUpdateAccessorInTheRootResource(ResourceNode resourceNode, String updateMethodName, + DataTransferChannel ch, ChannelMember cm, ResourcePath srcResPath, ResourcePath dstResPath, TypeDeclaration rootComponent, + int inDegree, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + ArrayList parameters; + VariableDeclaration param; + parameters = new ArrayList<>(); + String resourcePath = getUpdateResourcePathAndPathParams(dstResPath, parameters, true, platformSpec, langSpec); // Path parameters to identify the self resource. + ResourcePath resPath = new ResourcePath(dstResPath); + for (int i = 0; i < parameters.size(); i++) { + Parameter pathParam = new Parameter(parameters.get(i).getName()); + resPath.replacePathParam(i, pathParam, null); + } + for (Selector selector: ch.getAllSelectors()) { + if (selector.getExpression() instanceof Variable) { + Variable selVar = (Variable) selector.getExpression(); + VariableDeclaration chParam = langSpec.newVariableDeclaration(selVar.getType(), selVar.getName()); + if (!platformSpec.isMonolithic()) { + ((RestApiSpecific) platformSpec).addFormParamAnnotation(chParam, selVar.getName()); + } + parameters.add(chParam); // A channel parameter to specify the context of the collaboration. + } + } + Type srcType = srcResPath.getResourceStateType(); + String srcResName = langSpec.toVariableName(getComponentName(srcResPath.getResourceHierarchy(), langSpec)); + param = langSpec.newVariableDeclaration(srcType, srcResName); + if (!platformSpec.isMonolithic()) ((RestApiSpecific) platformSpec).addFormParamAnnotation(param, srcResName); + parameters.add(param); // The state of the source resource to carry the data-flow. + for (ResourcePath refRes: ch.getReferenceResources()) { + if (!refRes.equals(resourceNode.getInSideResource(ch))) { + String refName = langSpec.toVariableName(getComponentName(refRes.getResourceHierarchy(), langSpec)); + param = langSpec.newVariableDeclaration(refRes.getResourceStateType(), refName); + if (!platformSpec.isMonolithic()) { + ((RestApiSpecific) platformSpec).addFormParamAnnotation(param, refName); + } + parameters.add(param); + } + } + MethodDeclaration updateAccessor = langSpec.newMethodDeclaration(updateMethodName, false, null, parameters); + if (!platformSpec.isMonolithic()) { + if (isPut(cm)) { + ((RestApiSpecific) platformSpec).addPutAnnotations(updateAccessor); + } else { + if (!isDelete(cm)) { + ((RestApiSpecific) platformSpec).addPostAnnotations(updateAccessor); + } else { + ((RestApiSpecific) platformSpec).addDeleteAnnotations(updateAccessor); + } + } + } + if (inDegree > 1) { + // For each source resource, a child resource is defined in the destination resource so that its state can be updated separately. + resourcePath += "/" + langSpec.toVariableName(srcResName); + } + if (!platformSpec.isMonolithic()) ((RestApiSpecific) platformSpec).addPathAnnotation(updateAccessor, resourcePath); + + // To make the accessor call the update method. + Expression resExp = getPullAccessor(platformSpec).getDirectStateAccessorFor(resPath, resPath.getRoot()); + List args = new ArrayList<>(); + if (resExp instanceof Term) { + // to access the parent + if (((Term) resExp).getChildren().size() > 1 && ((Term) resExp).getChild(1) instanceof Variable) { + args.add(((Variable)((Term) resExp).getChild(1)).getName()); + } + resExp = ((Term) resExp).getChild(0); + } + String resourceAccess = resExp.toImplementation(new String[] {""}); + for (VariableDeclaration var: updateAccessor.getParameters()) { + args.add(var.getName()); + } + updateAccessor.addStatement(langSpec.getMethodInvocation(resourceAccess, updateMethodName, args)); + rootComponent.addMethod(updateAccessor); + } + + protected MethodDeclaration declareInputAccessorInTheRootResource(String inputMethodName, + ArrayList rootInputParams, ChannelMember cm, String resourcePath, + TypeDeclaration rootComponent, IPlatformSpecific platformSpec, ILanguageSpecific langSpec) { + MethodDeclaration rootInputAccessor; + rootInputAccessor = langSpec.newMethodDeclaration(inputMethodName, false, null, rootInputParams); + if (!platformSpec.isMonolithic()) { + if (isPut(cm)) { + ((RestApiSpecific) platformSpec).addPutAnnotations(rootInputAccessor); + } else { + if (!isDelete(cm)) { + ((RestApiSpecific) platformSpec).addPostAnnotations(rootInputAccessor); + } else { + ((RestApiSpecific) platformSpec).addDeleteAnnotations(rootInputAccessor); + } + } + if (resourcePath.length() > 0) { + ((RestApiSpecific) platformSpec).addPathAnnotation(rootInputAccessor, resourcePath); + } + } + rootComponent.addMethod(rootInputAccessor); + return rootInputAccessor; + } } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/ILanguageSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/ILanguageSpecific.java index baf40f3..5e5ea4a 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/ILanguageSpecific.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/ILanguageSpecific.java @@ -27,6 +27,7 @@ String getVariableDeclaration(String typeName, String varName); String getFieldInitializer(Type type, Expression initialValue); boolean declareField(); + String getSelfExp(); String getFieldAccessor(String fieldName); String getMethodInvocation(String methodName); String getMethodInvocation(String receiverName, List parameters); @@ -35,18 +36,25 @@ String getConstructorInvocation(String componentName, List parameters); String getReturnStatement(String returnValue); String getIfStatement(Term condition, String block); - String getForStatement(String varName, String list); - String getForStatement(String varName, String varType, String map); + String getForStatementForList(String varName, String list); + String getForStatementForCollection(String varName, String varType, String collection); + String getForStatementForMap(String varName, String varType, String map); String getEndForStatement(); String getEndForStatement(String varName); String toComponentName(String name); String toVariableName(String name); String getMainComponentName(); - String getTupleGet(String tupleExp, int idx, int length); - String getDecomposedTuple(String tupleExp, VariableDeclaration tupleVar, List vars); String getAssignment(); String getStatementDelimiter(); String getStringDelimiter(); + String getOpeningScoreDelimiter(); + String getClosingScoreDelimiter(); + String getValueToStringExp(String typeName, String valueExp); + String getStringToValueExp(String typeName, String strExp); + String getPairExp(String first, String second); + String getFirstEntryFromMapExp(String map); + String getTupleGet(String tupleExp, int idx, int length); + String getDecomposedTuple(String tupleExp, VariableDeclaration tupleVar, List vars); boolean isValueType(Type type); boolean isVoidType(Type type); } diff --git a/AlgebraicDataflowArchitectureModel/src/generators/IPlatformSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/IPlatformSpecific.java new file mode 100644 index 0000000..c609b7a --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/IPlatformSpecific.java @@ -0,0 +1,9 @@ +package generators; + +import java.util.List; + +public interface IPlatformSpecific { + boolean hasMain(); + boolean isMonolithic(); + boolean isDifferentTreesAsDifferentServices(); +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java index b39e9fc..b362030 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaCodeGenerator.java @@ -325,7 +325,7 @@ } } - // Declare the state field in the parent component. + // Declare the state field and reference fields in the parent component. if (component == null) { // Declare reference fields for push/pull data transfer. boolean noPullTransfer = true; @@ -610,7 +610,11 @@ if (exp instanceof Variable) { Variable pathVar = (Variable) exp; String varName = "self" + (v > 1 ? v : ""); -// String varName = pathVar.getName(); + VariableDeclaration pathParam = new VariableDeclaration(pathVar.getType(), varName); + params.add(pathParam); // A path parameter to identify the self resource. + } else if (exp instanceof Term) { + Term pathVar = (Term) exp; + String varName = "self" + (v > 1 ? v : ""); VariableDeclaration pathParam = new VariableDeclaration(pathVar.getType(), varName); params.add(pathParam); // A path parameter to identify the self resource. } @@ -623,10 +627,10 @@ params.add(chParam); // A channel parameter to specify the context of the collaboration. } } - params.add(new VariableDeclaration(srcResPath.getResourceStateType(), srcResPath.getLeafResourceName())); // The state of the source resource to carry the data-flow. + params.add(new VariableDeclaration(srcResPath.getResourceStateType(), toVariableName(getComponentName(srcResPath.getResourceHierarchy())))); // The state of the source resource to carry the data-flow. for (ResourcePath ref: ch.getReferenceResources()) { if (!ref.equals(resourceNode.getInSideResource(ch))) { - params.add(new VariableDeclaration(ref.getResourceStateType(), ref.getLeafResourceName())); + params.add(new VariableDeclaration(ref.getResourceStateType(), toVariableName(getComponentName(ref.getResourceHierarchy())))); } } MethodDeclaration update = null; @@ -663,7 +667,16 @@ VariableDeclaration refVar = new VariableDeclaration(new Type(resName, resName), toVariableName(resName)); if (component != null) { // A component is created for this resource. - component.addField(refField); + boolean existsField = false; + for (FieldDeclaration field: component.getFields()) { + if (field.getName().equals(refVar.getName())) { + existsField = true; + break; + } + } + if (!existsField) { + component.addField(refField); + } constructorParams.add(new AbstractMap.SimpleEntry<>(resourceNode.getResourceHierarchy(), refVar)); } else { // No component is created for this resource. @@ -970,16 +983,9 @@ private static Map> getDependedRootComponentGraph(DataTransferModel model) { Map> dependedComponentGraph = new HashMap<>(); for (Channel ch: model.getChannels()) { - DataTransferChannel dtCh = (DataTransferChannel) ch; Set inRes = new HashSet<>(); Set outRes = new HashSet<>(); - for (ChannelMember cm: dtCh.getChannelMembers()) { - if (cm.isOutside()) { - outRes.add(cm.getResource().getResourceHierarchy()); - } else { - inRes.add(cm.getResource().getResourceHierarchy()); - } - } + getDependedRootComponentGraphSub(ch, inRes, outRes, true); if (outRes.size() > 0 && inRes.size() > 0) { for (ResourceHierarchy out: outRes) { for (ResourceHierarchy in: inRes) { @@ -988,7 +994,9 @@ dependings = new HashSet<>(); dependedComponentGraph.put(out.getRoot(), dependings); } - dependings.add(in.getRoot()); + if (!out.getRoot().equals(in.getRoot())) { + dependings.add(in.getRoot()); + } } } } @@ -996,7 +1004,24 @@ return dependedComponentGraph; } - static private ArrayList determineResourceOrder(DataFlowGraph graph, Map> dependedRootComponentGraph) { + private static void getDependedRootComponentGraphSub(Channel ch, Set inRes, Set outRes, boolean isRoot) { + DataTransferChannel dtCh = (DataTransferChannel) ch; + for (ChannelMember cm: dtCh.getChannelMembers()) { + if (!isRoot && !cm.isOutside()) { + outRes.add(cm.getResource().getResourceHierarchy()); // dependency to a descendant channel resource. + } + if (cm.isOutside()) { + outRes.add(cm.getResource().getResourceHierarchy()); // dependency to an outside resource. + } else { + inRes.add(cm.getResource().getResourceHierarchy()); // dependency from an inside resource. + } + } + for (Channel childCh: ch.getChildren()) { + getDependedRootComponentGraphSub(childCh, inRes, outRes, false); + } + } + + private static ArrayList determineResourceOrder(DataFlowGraph graph, Map> dependedRootComponentGraph) { ArrayList resources = new ArrayList<>(); Set visited = new HashSet<>(); for (Node n : graph.getResourceNodes()) { @@ -1066,6 +1091,11 @@ } v++; } + ResourcePath resPath = new ResourcePath(resourceNode.getPrimaryResourcePath()); + for (int i = 0; i < mainGetterParams.size(); i++) { + Parameter pathParam = new Parameter(mainGetterParams.get(i).getName()); + resPath.replacePathParam(i, pathParam, null); + } if (mainGetterParams.size() > 0) { getterAccessor = new MethodDeclaration("get" + getComponentName(resourceNode.getResourceHierarchy()), false, @@ -1076,7 +1106,7 @@ getImplStateType(resourceNode.getResourceHierarchy())); } getterAccessor.setBody(new Block()); - Expression getState = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(resourceNode.getPrimaryResourcePath(), null); + Expression getState = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(resPath, null); getterAccessor.getBody().addStatement("return " + getState.toImplementation(new String[] {null}) + ";"); mainComponent.addMethod(getterAccessor); } @@ -1275,6 +1305,7 @@ if (!target.isOutside()) { return getDirectStateAccessorFor(targetRes, fromRes); } + // Get the next state by invoking a getter method. Term getter = null; String targetComponentName = getComponentName(targetRes.getResourceHierarchy()); if (generatesComponent(targetRes.getResourceHierarchy())) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java index 58eaa0f..f220abd 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaMethodBodyGenerator.java @@ -86,7 +86,6 @@ String dstResourceName = JavaCodeGenerator.getComponentName(dst.getResourceHierarchy()); TypeDeclaration srcComponent = componentMap.get(srcResourceName); TypeDeclaration dstComponent = componentMap.get(dstResourceName); -// DataTransferChannel ch = ((ChannelNode) resToCh.getDestination()).getChannel(); ChannelNode chNode = (ChannelNode) chToRes.getSource(); DataTransferChannel ch = chNode.getChannel(); for (ChannelMember out: ch.getOutputChannelMembers()) { @@ -120,9 +119,19 @@ } if (((StoreAttribute) dst.getAttribute()).isStored()) { // update stored state of dst side resource (when every incoming edge is in push style) + Term unifiedMassage = null; + if (directDstCh != ch) { + unifiedMassage = directDstCh.fillOutsideResourcePaths(out, JavaCodeGenerator.pushAccessor, null).getValue(); + } Expression updateExp = null; if (ch.getReferenceChannelMembers().size() == 0) { - updateExp = ch.deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor).getKey(); + Term message = ch.fillOutsideResourcePaths(out, JavaCodeGenerator.pushAccessor, null).getValue(); + if (unifiedMassage == null) { + unifiedMassage = message; + } else { + unifiedMassage = (Term) unifiedMassage.unify(message); + } + updateExp = ch.deriveUpdateExpressionOf(out, unifiedMassage, JavaCodeGenerator.pushAccessor); } else { // if there exists one or more reference channel member. HashMap inputResourceToStateAccessor = new HashMap<>(); @@ -132,7 +141,13 @@ for (ChannelMember c: ch.getReferenceChannelMembers()) { inputResourceToStateAccessor.put(c, JavaCodeGenerator.refAccessor); } - updateExp = ch.deriveUpdateExpressionOf(out, JavaCodeGenerator.pushAccessor, inputResourceToStateAccessor).getKey(); + Term message = ch.fillOutsideResourcePaths(out, JavaCodeGenerator.pushAccessor, inputResourceToStateAccessor).getValue(); + if (unifiedMassage == null) { + unifiedMassage = message; + } else { + unifiedMassage = (Term) unifiedMassage.unify(message); + } + updateExp = ch.deriveUpdateExpressionOf(out, unifiedMassage, JavaCodeGenerator.pushAccessor); } // Replace Json constructor with a constructor of a descendant resource. ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); @@ -209,6 +224,7 @@ updateStatement += "this." + JavaCodeGenerator.toVariableName(JavaCodeGenerator.getComponentName(outRes)) + " = " + newState + ";"; } } + // add an update statement of the state of dst side resource. if (numOfOutResourcesWithTheSameHierarchy == 1) { update.addFirstStatement(updateStatement); } else { @@ -249,8 +265,24 @@ update.addFirstStatement(ifStatement + "\t" + updateStatement.replace("\n", "\n\t") + "\n}"); } } - if (resToCh.getDestination().getIndegree() > 1 - || (resToCh.getDestination().getIndegree() == 1 && directDstCh.getInputChannelMembers().iterator().next().getStateTransition().isRightPartial())) { + // Calculate in-degree (PUSH transfer) of the destination resource. + int inDegree = 0; + Set inEdges = new HashSet<>(); + inEdges.addAll(chNode.getInEdges()); + for (ChannelNode ancestor: chNode.getAncestors()) { + inEdges.addAll(ancestor.getInEdges()); + } + for (ChannelNode descendant: chNode.getDescendants()) { + inEdges.addAll(descendant.getInEdges()); + } + for (Edge resToCh2: inEdges) { + DataFlowEdge df =(DataFlowEdge) resToCh2; + if (((PushPullAttribute) df.getAttribute()).getSelectedOption() == PushPullValue.PUSH) { + inDegree++; + } + } + if (inDegree > 1 + || (inDegree == 1 && directDstCh.getInputChannelMembers().iterator().next().getStateTransition().isRightPartial())) { // update a cache of src side resource (when incoming edges are multiple) String cacheStatement = "this." + JavaCodeGenerator.toVariableName(srcResourceName) + " = " + JavaCodeGenerator.toVariableName(srcResourceName) + ";"; if (update.getBody() == null || !update.getBody().getStatements().contains(cacheStatement)) { @@ -350,10 +382,14 @@ } } // Update fields to refer to outside resources. + ResourcePath filledOutsideResourcePath = null; Map>> resourcePaths = ch.fillOutsideResourcePaths(out, JavaCodeGenerator.pullAccessor); if (resourcePaths != null && resourcePaths.size() > 0) { for (ChannelMember outsideMember: resourcePaths.keySet()) { ResourcePath outsidePath = resourcePaths.get(outsideMember).getKey(); + if (out.equals(outsideMember)) { + filledOutsideResourcePath = outsidePath; + } if (!JavaCodeGenerator.generatesComponent(outsidePath.getResourceHierarchy())) { outsidePath = outsidePath.getParent(); } @@ -378,11 +414,17 @@ } } // Values of path parameters to call the update method. + if (filledOutsideResourcePath == null) { + filledOutsideResourcePath = dstRes; + } String pathParams = ""; - for (Expression pathParam: dstRes.getPathParams()) { + for (Expression pathParam: filledOutsideResourcePath.getPathParams()) { if (pathParam instanceof Variable) { Variable pathVar = (Variable) pathParam; pathParams += pathVar.getName() + ", "; + } else if (pathParam instanceof Constant) { + Constant pathVar = (Constant) pathParam; + pathParams += pathVar.getSymbol().getName() + ", "; } } // Values of channel parameters to call the update method. @@ -393,6 +435,11 @@ chParams += selVar.getName() + ", "; } } + // Value of the source side (input side) resource. + String srcFieldName = "value"; + if (!JavaCodeGenerator.generatesComponent(src.getResourceHierarchy())) { + srcFieldName = JavaCodeGenerator.toVariableName(srcResourceName); + } // Call the update method. String updateMethodName = null; if (JavaCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { @@ -400,11 +447,6 @@ } else { updateMethodName = "update" + dstResourceName + "From" + srcResourceName; } - // Value of the source side (input side) resource. - String srcFieldName = "value"; - if (!JavaCodeGenerator.generatesComponent(src.getResourceHierarchy())) { - srcFieldName = JavaCodeGenerator.toVariableName(srcResourceName); - } if (!outsideOutputResource) { // The destination resource is not outside. if (srcComponent != dstComponent) { @@ -414,17 +456,17 @@ } } else { // Use the reference field to refer to outside destination resource. - srcUpdate.addStatement("this." + JavaCodeGenerator.toVariableName(dstComponent.getTypeName()) + "." + updateMethodName + "(" + pathParams + chParams + srcFieldName + refParams + ");"); + srcUpdate.addStatement("this." + JavaCodeGenerator.toVariableName(dstComponent.getTypeName()) + "." + updateMethodName + "(" + pathParams + chParams + srcFieldName + refParams + ");"); } if (descendantDstChannels.contains(chNode)) { // For hierarchical channels (broadcasting push transfer). if (ch.getSelectors() != null && ch.getSelectors().size() > 0) { Expression selExp = ch.getSelectors().get(0).getExpression(); Type selType = null; - String varName = null; + String forVarName = null; if (selExp instanceof Variable) { selType = ((Variable) selExp).getType(); - varName = ((Variable) selExp).getName(); + forVarName = ((Variable) selExp).getName(); ChannelMember insideChMem = null; for (ChannelMember cm :ch.getInputChannelMembers()) { if (!cm.isOutside()) { @@ -453,15 +495,15 @@ insideResPath = insideResPath.getParent(); } insideResPath = insideResPath.getParent(); - String parent = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, src.getPrimaryResourcePath()).toImplementation(new String[] {}); if (insideResPath != null) { + String parent = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, src.getOutSideResource(directDstCh)).toImplementation(new String[] {}); if (selType.equals(DataConstraintModel.typeInt)) { // make a for loop (for a list) for broadcasting. - srcUpdate.addFirstStatement("for (int " + varName + " = 0; " + varName +" < " + parent + ".size(); " + varName + "++) {"); + srcUpdate.addFirstStatement("for (int " + forVarName + " = 0; " + forVarName +" < " + parent + ".size(); " + forVarName + "++) {"); srcUpdate.addStatement("}"); } else if (selType.equals(DataConstraintModel.typeString)) { // make a for loop (for a map) for broadcasting. - srcUpdate.addFirstStatement("for (String " + varName + ": " + parent + ".keySet()) {"); + srcUpdate.addFirstStatement("for (String " + forVarName + ": " + parent + ".keySet()) {"); srcUpdate.addStatement("}"); } } @@ -501,10 +543,14 @@ } } // Update fields to refer to outside resources. + ResourcePath filledOutsideResourcePath = null; Map>> resourcePaths = ch.fillOutsideResourcePaths(out, JavaCodeGenerator.pullAccessor); if (resourcePaths != null && resourcePaths.size() > 0) { for (ChannelMember outsideMember: resourcePaths.keySet()) { ResourcePath outsidePath = resourcePaths.get(outsideMember).getKey(); + if (out.equals(outsideMember)) { + filledOutsideResourcePath = outsidePath; + } if (!JavaCodeGenerator.generatesComponent(outsidePath.getResourceHierarchy())) { outsidePath = outsidePath.getParent(); } @@ -529,11 +575,17 @@ } } // Values of path parameters to call the update method. + if (filledOutsideResourcePath == null) { + filledOutsideResourcePath = dstRes; + } String pathParams = ""; - for (Expression pathParam: dstRes.getPathParams()) { + for (Expression pathParam: filledOutsideResourcePath.getPathParams()) { if (pathParam instanceof Variable) { Variable pathVar = (Variable) pathParam; pathParams += pathVar.getName() + ", "; + } else if (pathParam instanceof Constant) { + Constant pathVar = (Constant) pathParam; + pathParams += pathVar.getSymbol().getName() + ", "; } } // Values of channel parameters to call the update method. @@ -604,8 +656,8 @@ insideResPath = insideResPath.getParent(); } insideResPath = insideResPath.getParent(); - String parent = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, src.getPrimaryResourcePath()).toImplementation(new String[] {}); if (insideResPath != null) { + String parent = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, src.getOutSideResource(directDstCh)).toImplementation(new String[] {}); if (selType.equals(DataConstraintModel.typeInt)) { // make a for loop (for a list) for broadcasting. srcInput.addFirstStatement("for (int " + varName + " = 0; " + varName +" < " + parent + ".size(); " + varName + "++) {"); @@ -777,8 +829,8 @@ insideResPath = insideResPath.getParent(); } insideResPath = insideResPath.getParent(); - String parent = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, src.getPrimaryResourcePath()).toImplementation(new String[] {}); if (insideResPath != null) { + String parent = JavaCodeGenerator.pullAccessor.getDirectStateAccessorFor(insideResPath, dst.getInSideResource(ch)).toImplementation(new String[] {}); if (selType.equals(DataConstraintModel.typeInt)) { // make a for loop (for a list) for data collecting. getter.addFirstStatement("for (int " + varName + " = 0; " + varName +" < " + parent + ".size(); " + varName + "++) {"); @@ -1231,6 +1283,7 @@ } private static void replaceJsonTermWithConstructorInvocation(Expression exp, Type replacedJsonType, String replacingClassName, TypeDeclaration descendantComponent) { + // Replace each json term in exp with the corresponding constructor invocation. Type descendantType = new Type(replacingClassName, replacingClassName); Map subTerms = ((Term) exp).getSubTerms(Term.class); Iterator> termEntItr = subTerms.entrySet().iterator(); @@ -1245,10 +1298,11 @@ String delimiter = ""; if (descendantConstructor != null) { for (VariableDeclaration var: descendantConstructor.getParameters()) { + // Extract the argument of each constructor parameter from jsonTerm. JsonAccessor jsonMember = new JsonAccessor(DataConstraintModel.dot); jsonMember.addChild(jsonTerm); jsonMember.addChild(new Constant(var.getName(), DataConstraintModel.typeString)); - Expression param = jsonMember.reduce(); + Expression param = jsonMember.reduce(); // Reduce {"name": "foo", age: 25}.name => "foo" if (param != null) { if (param instanceof Term) { if (((Term) param).getType() == null) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JavaSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/JavaSpecific.java index dfe5850..58357f2 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JavaSpecific.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JavaSpecific.java @@ -117,6 +117,11 @@ } @Override + public String getSelfExp() { + return self; + } + + @Override public String getFieldAccessor(String fieldName) { return self + "." + fieldName; } @@ -168,7 +173,7 @@ @Override public String getConstructorInvocation(String componentName, List parameters) { String invocation = "new " + componentName + "("; - if (parameters.size() > 0) { + if (parameters != null && parameters.size() > 0) { for (int i = 0; i < parameters.size(); i++) { if (i < parameters.size() - 1) { invocation += parameters.get(i) + ", "; @@ -192,12 +197,17 @@ } @Override - public String getForStatement(String varName, String list) { + public String getForStatementForList(String varName, String list) { return "for (int " + varName + getAssignment() + "0; " + varName + " < " + list + ".size(); " + varName + "++) {"; } @Override - public String getForStatement(String varName, String varType, String map) { + public String getForStatementForCollection(String varName, String varType, String collection) { + return "for (" + varType + " " + varName + ": " + collection + ") {"; + } + + @Override + public String getForStatementForMap(String varName, String varType, String map) { return "for (" + varType + " " + varName + ": " + map + ".keySet()) {"; } @@ -242,6 +252,58 @@ } @Override + public String getOpeningScoreDelimiter() { + return "{"; + } + + @Override + public String getClosingScoreDelimiter() { + return "}"; + } + + @Override + public String getValueToStringExp(String typeName, String valueExp) { + if (typeName.equals("int")) { + return "Integer.toString(" + valueExp + ")"; + } else if (typeName.equals("float")) { + return "Float.toString(" + valueExp + ")"; + } else if (typeName.equals("double")) { + return "Double.toString(" + valueExp + ")"; + } else if (typeName.equals("boolean")) { + return "Boolean.toString(" + valueExp + ")"; + } else { + return valueExp + ".toString()"; + } + } + + @Override + public String getStringToValueExp(String typeName, String strExp) { + if (typeName.equals("int")) { + return "Integer.parseInt(" + strExp + ")"; + } else if (typeName.equals("float")) { + return "Float.parseFloat(" + strExp + ")"; + } else if (typeName.equals("double")) { + return "Double.parseDouble(" + strExp + ")"; + } else if (typeName.equals("boolean")) { + return "Boolean.parseBoolean(" + strExp + ")"; + } else if (typeName.startsWith("ArrayList") || typeName.startsWith("List")) { + return "Arrays.asList(" + strExp + ".replace(\"[\",\"\").replace(\"]\",\"\").split(\",\",0))"; + } else { + return strExp; + } + } + + @Override + public String getPairExp(String first, String second) { + return getConstructorInvocation(DataConstraintModel.typeTuple.getImplementationTypeName() + "<>", List.of(first, second)); + } + + @Override + public String getFirstEntryFromMapExp(String map) { + return getMethodInvocation(map, "entrySet().iterator().next"); + } + + @Override public String getTupleGet(String tupleExp, int idx, int length) { Expression t = new Variable(tupleExp, DataConstraintModel.typeTuple); for (int i = 0; i < idx; i++) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java index ae93b32..9ff7cfb 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyCodeGenerator.java @@ -185,15 +185,16 @@ // leaf resource. Type fieldType = getImplStateType(res); component.addField(new FieldDeclaration(fieldType, "value", getInitializer(res))); - Map nameToParam = constructorParams.get(res); - if (nameToParam == null) { - nameToParam = new HashMap<>(); - constructorParams.put(resourceNode.getResourceHierarchy(), nameToParam); - } - String varName = toVariableName(resourceName); - if (nameToParam.get(varName) == null) { - nameToParam.put(varName, new VariableDeclaration(fieldType, varName)); - } + // Add a parameter to initialize the state field to the constructor. +// Map nameToParam = constructorParams.get(res); +// if (nameToParam == null) { +// nameToParam = new HashMap<>(); +// constructorParams.put(resourceNode.getResourceHierarchy(), nameToParam); +// } +// String varName = "value"; +// if (nameToParam.get(varName) == null) { +// nameToParam.put(varName, new VariableDeclaration(fieldType, varName)); +// } } else { ResourceHierarchy child = children.iterator().next(); if (children.size() == 1 && child.getNumParameters() > 0) { @@ -458,7 +459,11 @@ getImplStateType(resourceNode.getResourceHierarchy())); } getterAccessor.setBody(new Block()); - ResourcePath resPath = resourceNode.getPrimaryResourcePath(); + ResourcePath resPath = new ResourcePath(resourceNode.getPrimaryResourcePath()); + for (int i = 0; i < mainGetterParams.size(); i++) { + Parameter pathParam = new Parameter(mainGetterParams.get(i).getName()); + resPath.replacePathParam(i, pathParam, null); + } Expression getState = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(resPath, resPath.getRoot()); getterAccessor.getBody().addStatement("return " + getState.toImplementation(new String[] {null}) + ";"); @@ -673,9 +678,10 @@ params.add(param); // The state of the source resource to carry the data-flow. for (ResourcePath refRes: ch.getReferenceResources()) { if (!refRes.equals(resourceNode.getInSideResource(ch))) { - param = new VariableDeclaration(refRes.getResourceStateType(), refRes.getLeafResourceName()); - if (isRestAPI) param.addAnnotation(new Annotation("FormParam", "\"" + refRes.getLeafResourceName() + "\"")); - params.add(param); + String refName = toVariableName(getComponentName(refRes.getResourceHierarchy())); + param = new VariableDeclaration(refRes.getResourceStateType(), refName); + if (isRestAPI) param.addAnnotation(new Annotation("FormParam", "\"" + refName + "\"")); + params.add(param); } } MethodDeclaration update = null; @@ -801,8 +807,9 @@ params.add(param); // The state of the source resource to carry the data-flow. for (ResourcePath refRes: ch.getReferenceResources()) { if (!refRes.equals(resourceNode.getInSideResource(ch))) { - param = new VariableDeclaration(refRes.getResourceStateType(), refRes.getLeafResourceName()); - param.addAnnotation(new Annotation("FormParam", "\"" + refRes.getLeafResourceName() + "\"")); + String refName = toVariableName(getComponentName(refRes.getResourceHierarchy())); + param = new VariableDeclaration(refRes.getResourceStateType(), refName); + param.addAnnotation(new Annotation("FormParam", "\"" + refName + "\"")); params.add(param); } } @@ -850,7 +857,7 @@ // In each resource. ArrayList resInputParams = new ArrayList<>(); ArrayList rootInputParams = new ArrayList<>(); - String resourcePath = getInputMethodResourcePathAndPathParams(cm.getResource(), resInputParams, rootInputParams); // Path parameters for the input REST API. + String resourcePath = getInputMethodResourcePathAndPathParams(cm.getResource(), rootInputParams); // Path parameters for the input REST API. if (resourcePath.indexOf('/') > 0) { resourcePath = resourcePath.substring(resourcePath.indexOf('/')); } else { @@ -1295,7 +1302,7 @@ return resPath.getResourceHierarchy().toResourcePath(params); } - private static String getInputMethodResourcePathAndPathParams(ResourcePath resPath, ArrayList resInputParams, ArrayList rootInputParams) { + private static String getInputMethodResourcePathAndPathParams(ResourcePath resPath, ArrayList rootInputParams) { int v = 1; List params = new ArrayList<>(); if (resPath.getLastParam() != null) { @@ -1455,6 +1462,7 @@ return getDirectStateAccessorFor(targetRes, fromRes); } } + // Get the next state through a local variable which is to be initialized by a response of a GET API. return new Parameter(toVariableName(getComponentName(targetRes.getResourceHierarchy())), targetRes.getResourceStateType() != null ? targetRes.getResourceStateType() : DataConstraintModel.typeInt); diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java index 706eec2..cbef7e0 100644 --- a/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseyMethodBodyGenerator.java @@ -131,30 +131,35 @@ } if (((StoreAttribute) dst.getAttribute()).isStored()) { // update stored state of dst side resource (when every incoming edge is in push style) + Term unifiedMassage = null; + if (directDstCh != ch) { + unifiedMassage = directDstCh.fillOutsideResourcePaths(out, JerseyCodeGenerator.pushAccessor, null).getValue(); + } Expression updateExp = null; if (ch.getReferenceChannelMembers().size() == 0) { - updateExp = ch.deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor).getKey(); + Term message = ch.fillOutsideResourcePaths(out, JerseyCodeGenerator.pushAccessor, null).getValue(); + if (unifiedMassage == null) { + unifiedMassage = message; + } else { + unifiedMassage = (Term) unifiedMassage.unify(message); + } + updateExp = ch.deriveUpdateExpressionOf(out, unifiedMassage, JerseyCodeGenerator.pushAccessor); } else { // if there exists one or more reference channel member. HashMap inputResourceToStateAccessor = new HashMap<>(); - for (Edge chToRes2: dst.getInEdges()) { - DataTransferChannel ch2 = ((ChannelNode) chToRes2.getSource()).getChannel(); - for (Edge resToCh2: chToRes2.getSource().getInEdges()) { - DataFlowEdge dIn = (DataFlowEdge) resToCh2; - ChannelMember in2 = null; - for (ChannelMember cm: ch2.getInputChannelMembers()) { - if (((ResourceNode) dIn.getSource()).getOutSideResources().contains(cm.getResource())) { - in2 = cm; - break; - } - } - inputResourceToStateAccessor.put(in2, JerseyCodeGenerator.pushAccessor); - } + for (ChannelMember c: ch.getInputChannelMembers()) { + inputResourceToStateAccessor.put(c, JerseyCodeGenerator.pushAccessor); } for (ChannelMember c: ch.getReferenceChannelMembers()) { inputResourceToStateAccessor.put(c, JerseyCodeGenerator.refAccessor); } - updateExp = ch.deriveUpdateExpressionOf(out, JerseyCodeGenerator.pushAccessor, inputResourceToStateAccessor).getKey(); + Term message = ch.fillOutsideResourcePaths(out, JerseyCodeGenerator.pushAccessor, inputResourceToStateAccessor).getValue(); + if (unifiedMassage == null) { + unifiedMassage = message; + } else { + unifiedMassage = (Term) unifiedMassage.unify(message); + } + updateExp = ch.deriveUpdateExpressionOf(out, unifiedMassage, JerseyCodeGenerator.pushAccessor); } // Replace Json constructor with a constructor of a descendant resource. ResourceHierarchy outRes = out.getResource().getResourceHierarchy(); @@ -197,6 +202,9 @@ if (JerseyCodeGenerator.generatesComponent(outRes)) { if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { updateStatement = sideEffects[0]; + if (updateStatement.endsWith("\n")) { + updateStatement = updateStatement.substring(0, updateStatement.length() - 1); + } } else { updateStatement = sideEffects[0] + "this.value = " + newState + ";"; } @@ -204,6 +212,9 @@ if (sideEffects[0] != null) { updateStatement = sideEffects[0]; updateStatement = updateStatement.replace(".value", "." + JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(outRes))); + if (updateStatement.endsWith("\n")) { + updateStatement = updateStatement.substring(0, updateStatement.length() - 1); + } } if (DataConstraintModel.typeList.isAncestorOf(outRes.getParent().getResourceStateType())) { Term selector = new Term(DataConstraintModel.set); @@ -266,17 +277,22 @@ update.addFirstStatement(ifStatement + "\t" + updateStatement.replace("\n", "\n\t") + "\n}"); } } - // Calculate in-degree of the destination resource. - Set inResources = new HashSet<>(); - for (ResourceNode rn: graph.getResourceNodes(out.getResource().getResourceHierarchy())) { - // ResourceNodes that have the same ResourceHierarchy. - for (Edge chToRes2: rn.getInEdges()) { - for (Edge resToCh2: chToRes2.getSource().getInEdges()) { - inResources.add(((ResourceNode) resToCh2.getSource()).getResourceHierarchy()); - } + // Calculate in-degree (PUSH transfer) of the destination resource. + int inDegree = 0; + Set inEdges = new HashSet<>(); + inEdges.addAll(chNode.getInEdges()); + for (ChannelNode ancestor: chNode.getAncestors()) { + inEdges.addAll(ancestor.getInEdges()); + } + for (ChannelNode descendant: chNode.getDescendants()) { + inEdges.addAll(descendant.getInEdges()); + } + for (Edge resToCh2: inEdges) { + DataFlowEdge df =(DataFlowEdge) resToCh2; + if (((PushPullAttribute) df.getAttribute()).getSelectedOption() == PushPullValue.PUSH) { + inDegree++; } } - int inDegree = inResources.size(); if (inDegree > 1 || (inDegree == 1 && directDstCh.getInputChannelMembers().iterator().next().getStateTransition().isRightPartial())) { // update a cache of src side resource (when incoming edges are multiple) @@ -295,7 +311,12 @@ MethodDeclaration update2 = update; update = getMethod(rootComponent, update2.getName()); // get the accessor to the update method. // To make the accessor call the update method. - Expression resExp = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(out.getResource(), out.getResource().getRoot()); + ResourcePath outResPath = new ResourcePath(out.getResource()); + for (int i = 0; i < outResPath.getPathParams().size(); i++) { + Parameter pathParam = new Parameter(update.getParameters().get(i).getName()); + outResPath.replacePathParam(i, pathParam, null); + } + Expression resExp = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(outResPath, outResPath.getRoot()); String args = ""; String delimiter = ""; if (resExp instanceof Term) { @@ -312,8 +333,8 @@ if (v < out.getResource().getPathParams().size()) { if (out.getResource().getPathParams().get(v) instanceof Variable) { args += delimiter + ((Variable) out.getResource().getPathParams().get(v)).getName(); - } else if (out.getResource().getPathParams().get(v) instanceof JsonAccessor) { - args += delimiter + ((JsonAccessor) out.getResource().getPathParams().get(v)).toImplementation(new String[] {}); // ToDo. + } else if (out.getResource().getPathParams().get(v) instanceof Term) { + args += delimiter + "v" + (v + 1); } } else { args += delimiter + var.getName(); @@ -409,16 +430,19 @@ getter.addStatement("return " + dstResName + ";"); } } else { + String[] sideEffects = new String[] {""}; if (DataConstraintModel.typeList.isAncestorOf(dst.getParent().getResourceStateType())) { Term selector = new Term(DataConstraintModel.get); selector.addChild(new Field("value")); selector.addChild(dst.getSelectors().get(dst.getSelectors().size() - 1).getExpression()); - getter.addStatement("return " + selector.toImplementation(new String[] {}) + ";"); + String curState = selector.toImplementation(sideEffects); + getter.addStatement(sideEffects[0] + "return " + curState + ";"); } else if (DataConstraintModel.typeMap.isAncestorOf(dst.getParent().getResourceStateType())) { Term selector = new Term(DataConstraintModel.lookup); selector.addChild(new Field("value")); selector.addChild(dst.getSelectors().get(dst.getSelectors().size() - 1).getExpression()); - getter.addStatement("return " + selector.toImplementation(new String[] {}) + ";"); + String curState = selector.toImplementation(sideEffects); + getter.addStatement(sideEffects[0] + "return " + curState + ";"); } } } @@ -456,6 +480,7 @@ } params.add(new AbstractMap.SimpleEntry<>(src.getResourceStateType(), new AbstractMap.SimpleEntry<>(JerseyCodeGenerator.toVariableName(srcResourceName), srcFieldName))); + // Get the value of reference member to call the update method. Set referredSet = referredResources.get(srcUpdate); if (ch.getReferenceChannelMembers().size() > 0) { for (ChannelMember rc: ch.getReferenceChannelMembers()) { @@ -504,14 +529,15 @@ if (inDegree <= 1) { srcResName = null; } - Entry> filledEntry = ch.fillOutsideResourcePaths(out, JerseyCodeGenerator.pushAccessor).get(out); + Map>> filledPaths = ch.fillOutsideResourcePaths(out, JerseyCodeGenerator.pushAccessor); String dstPath = null; - if (filledEntry != null) { - ResourcePath filledDstPath = filledEntry.getKey(); + if (filledPaths != null && filledPaths.get(out) != null) { + ResourcePath filledDstPath = filledPaths.get(out).getKey(); dstPath = filledDstPath.toString().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); } else { dstPath = dstRes.getResourceHierarchy().toResourcePath(pathParams); } + // Call the update method. if (!chainedCalls.contains(srcUpdate)) { // The first call to an update method in this method srcUpdate.addStatement(getHttpMethodParamsStatement(srcComponent.getTypeName(), params, true)); @@ -586,7 +612,7 @@ } srcUpdate.addThrow("JsonProcessingException"); } else { - // Inner-service + // Intra-service String updateMethodName = null; if (JerseyCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { updateMethodName = "updateFrom" + srcResourceName; @@ -608,6 +634,7 @@ callParams += delimiter + paramEnt.getValue().getValue(); delimiter = ", "; } + // Call the update method. if (srcComponent != dstComponent) { srcUpdate.addStatement("this." + JerseyCodeGenerator.toVariableName(dstResourceName) + "." + updateMethodName + "(" + callParams + ");"); } else { @@ -638,6 +665,7 @@ } params.add(new AbstractMap.SimpleEntry<>(src.getResourceStateType(), new AbstractMap.SimpleEntry<>(JerseyCodeGenerator.toVariableName(srcResourceName), srcFieldName))); + // Get the value of reference member to call the update method. Set referredSet = referredResources.get(srcInput); for (ChannelMember rc: ch.getReferenceChannelMembers()) { // For each reference channel member, get the current state of the reference side resource by pull data transfer. @@ -684,14 +712,15 @@ if (inDegree <= 1) { srcResName = null; } - Entry> filledEntry = ch.fillOutsideResourcePaths(out, JerseyCodeGenerator.pushAccessor).get(out); + Map>> filledPaths = ch.fillOutsideResourcePaths(out, JerseyCodeGenerator.pushAccessor); String dstPath = null; - if (filledEntry != null) { - ResourcePath filledDstPath = filledEntry.getKey(); + if (filledPaths != null && filledPaths.get(out) != null) { + ResourcePath filledDstPath = filledPaths.get(out).getKey(); dstPath = filledDstPath.toString().replaceAll(":.*\\}","\\}").replaceAll("\\{", "\"+").replaceAll("\\}", "+\""); } else { dstPath = dstRes.getResourceHierarchy().toResourcePath(pathParams); } + // Call the update method. if (!chainedCalls.contains(srcInput)) { // First call to an update method in this method srcInput.addStatement(getHttpMethodParamsStatement(srcComponent.getTypeName(), params, true)); @@ -707,10 +736,10 @@ if (ch.getSelectors() != null && ch.getSelectors().size() > 0) { Expression selExp = ch.getSelectors().get(0).getExpression(); Type selType = null; - String varName = null; + String forVarName = null; if (selExp instanceof Variable) { selType = ((Variable) selExp).getType(); - varName = ((Variable) selExp).getName(); + forVarName = ((Variable) selExp).getName(); ChannelMember insideChMem = null; for (ChannelMember cm :ch.getInputChannelMembers()) { if (!cm.isOutside()) { @@ -751,11 +780,11 @@ if (insideResPath != null) { if (selType.equals(DataConstraintModel.typeInt)) { // make a for loop (for a list) for broadcasting. - srcInput.addFirstStatement("for (int " + varName + " = 0; " + varName +" < " + parent + ".size(); " + varName + "++) {"); + srcInput.addFirstStatement("for (int " + forVarName + " = 0; " + forVarName +" < " + parent + ".size(); " + forVarName + "++) {"); srcInput.addStatement("}"); } else if (selType.equals(DataConstraintModel.typeString)) { // make a for loop (for a map) for broadcasting. - srcInput.addFirstStatement("for (String " + varName + ": " + parent + ".keySet()) {"); + srcInput.addFirstStatement("for (String " + forVarName + ": " + parent + ".keySet()) {"); srcInput.addStatement("}"); } } @@ -766,7 +795,7 @@ } srcInput.addThrow("JsonProcessingException"); } else { - // Inner-service + // Intra-service String updateMethodName = null; if (JerseyCodeGenerator.generatesComponent(dst.getResourceHierarchy())) { updateMethodName = "updateFrom" + srcResourceName; @@ -788,6 +817,7 @@ callParams += delimiter + paramEnt.getValue().getValue(); delimiter = ", "; } + // Call the update method. if (srcComponent != dstComponent) { srcInput.addStatement("this." + JerseyCodeGenerator.toVariableName(dstResourceName) + "." + updateMethodName + "(" + callParams + ");"); } else { @@ -812,6 +842,8 @@ } if (getter.getBody() == null || getter.getBody().getStatements().size() == 0) { // The first time to fill the getter method's body. + + // Data transfer on the same channel hierarchy. String[] sideEffects = new String[] {""}; // For each reference channel member, get the current state of the reference side resource by pull data transfer. for (ChannelMember rc: ch.getReferenceChannelMembers()) { @@ -837,14 +869,19 @@ getter.addFirstStatement(sideEffects[0] + refTypeName + " " + refResourceName + " = " + refExp + ";"); } } + + // Construct the base message. Map.Entry>>, Term> resourcePathsAndMessage = ch.fillOutsideResourcePaths(out, JerseyCodeGenerator.pullAccessor, null); Map>> resourcePaths = resourcePathsAndMessage.getKey(); Term messageTerm = resourcePathsAndMessage.getValue(); + + // Data transfer from path depending resource. for (Entry>> pathEnt: resourcePaths.entrySet()) { ChannelMember cm = pathEnt.getKey(); ResourcePath src2 = pathEnt.getValue().getKey(); - // get outside src resource state by pull data transfer. + // get outside src2 resource state by pull data transfer. if (cm.isOutside() || src2.getCommonPrefix(dst.getInSideResource(ch)) == null) { + // Data transfer from an outside input resource is regarded as PULL transfer. List pathParams = new ArrayList<>(); for (Expression pathExp: src2.getPathParams()) { sideEffects = new String[] {""}; @@ -857,17 +894,19 @@ generatePullDataTransfer(getter, srcResName2, srcPath2, srcResourceType); } } - // Should take into account the channel hierarchy. + + // Data transfer from the descendant channel hierarchies. Stack> channelItrStack = new Stack<>(); DataTransferChannel curChannel = ch; if (curChannel.getChildren() != null && curChannel.getChildren().size() > 0) { - // retrieve descendant channels recursively. + // retrieve descendant channels recursively. + // (For each descendant channel, data transfer from every input resource is regarded as PULL transfer.) Iterator chItr = curChannel.getChildren().iterator(); do { if (!chItr.hasNext()) { chItr = channelItrStack.pop(); } else { - curChannel = (DataTransferChannel) chItr.next(); + curChannel = (DataTransferChannel) chItr.next(); // generate pull data transfers. Set chMems = new HashSet<>(curChannel.getInputChannelMembers()); chMems.addAll(curChannel.getReferenceChannelMembers()); @@ -1233,6 +1272,9 @@ String updateStatement; if (updateExp instanceof Term && ((Term) updateExp).getSymbol().isImplWithSideEffect()) { updateStatement = sideEffects[0]; + if (updateStatement.endsWith("\n")) { + updateStatement = updateStatement.substring(0, updateStatement.length() - 1); + } } else { updateStatement = sideEffects[0] + "this.value = " + newState + ";"; } @@ -1244,6 +1286,9 @@ if (sideEffects[0] != null) { updateStatement = sideEffects[0]; updateStatement = updateStatement.replace(".value", "." + JerseyCodeGenerator.toVariableName(JerseyCodeGenerator.getComponentName(resource))); + if (updateStatement.endsWith("\n")) { + updateStatement = updateStatement.substring(0, updateStatement.length() - 1); + } } if (DataConstraintModel.typeList.isAncestorOf(resource.getParent().getResourceStateType())) { Term selector = new Term(DataConstraintModel.set); @@ -1280,8 +1325,13 @@ } MethodDeclaration inputAccessor = getMethod(componentMap.get(JerseyCodeGenerator.getComponentName(resource.getRoot())), inputAccessorName); if (inputAccessor != null) { + ResourcePath outResPath = new ResourcePath(out.getResource()); + for (int i = 0; i < outResPath.getPathParams().size(); i++) { + Parameter pathParam = new Parameter(inputAccessor.getParameters().get(i).getName()); + outResPath.replacePathParam(i, pathParam, null); + } // The expression of the receiver (resource) of the input method. - Expression resExp = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(out.getResource(), out.getResource().getRoot()); + Expression resExp = JerseyCodeGenerator.pullAccessor.getDirectStateAccessorFor(outResPath, outResPath.getRoot()); String args = ""; String delimiter = ""; if (resExp instanceof Term) { @@ -1326,6 +1376,7 @@ } private static void replaceJsonTermWithConstructorInvocation(Expression exp, Type replacedJsonType, String replacingClassName, TypeDeclaration descendantComponent) { + // Replace each json term in exp with the corresponding constructor invocation. Type descendantType = new Type(replacingClassName, replacingClassName); Map subTerms = ((Term) exp).getSubTerms(Term.class); Iterator> termEntItr = subTerms.entrySet().iterator(); @@ -1340,10 +1391,11 @@ if (descendantConstructor != null) { String delimiter = ""; for (VariableDeclaration var: descendantConstructor.getParameters()) { + // Extract the argument of each constructor parameter from jsonTerm. JsonAccessor jsonMember = new JsonAccessor(DataConstraintModel.dot); jsonMember.addChild(jsonTerm); jsonMember.addChild(new Constant(var.getName(), DataConstraintModel.typeString)); - Expression param = jsonMember.reduce(); + Expression param = jsonMember.reduce(); // Reduce {"name": "foo", age: 25}.name => "foo" if (param != null) { if (param instanceof Term) { if (((Term) param).getType() == null) { @@ -1466,7 +1518,7 @@ || elmType == DataConstraintModel.typeLong || elmType == DataConstraintModel.typeFloat || elmType == DataConstraintModel.typeDouble) { - String elmVal = CodeUtil.getToValueExp(elmType.getImplementationTypeName(), elementBase + ".getKey()"); + String elmVal = new JavaSpecific().getStringToValueExp(elmType.getImplementationTypeName(), elementBase + ".getKey()"); decoded = decoded.replace("$x", "new AbstractMap.SimpleEntry<>(" + elmVal + ", $x)"); } else if (elmType == DataConstraintModel.typeString) { decoded = decoded.replace("$x", "new AbstractMap.SimpleEntry<>(" + elementBase + ".getKey(), $x)"); @@ -1499,7 +1551,7 @@ || keyType == DataConstraintModel.typeDouble) { decoded += "for (String k: " + mapVal + ".keySet()) {\n"; decoded += "\t" + mapVar + ".put("; - keyVal = CodeUtil.getToValueExp(keyType.getImplementationTypeName(), "k"); + keyVal = new JavaSpecific().getStringToValueExp(keyType.getImplementationTypeName(), "k"); decoded += keyVal + ", " + mapVal + ".get(" + keyVal + ")" + ");\n"; decoded += "}"; } else if (keyType == DataConstraintModel.typeString) { @@ -1537,7 +1589,7 @@ // typeTuple: {"1.0":2.0}, typePair: {"left": 1.0, "right":2.0} statements += "form.param(\"" + paramName + "\", new ObjectMapper().writeValueAsString(" + value + "));\n"; } else { - statements += "form.param(\"" + paramName + "\", " + CodeUtil.getToStringExp(paramType.getImplementationTypeName(), value) + ");\n"; + statements += "form.param(\"" + paramName + "\", " + new JavaSpecific().getValueToStringExp(paramType.getImplementationTypeName(), value) + ");\n"; } } if (isFirstCall) { diff --git a/AlgebraicDataflowArchitectureModel/src/generators/JerseySpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/JerseySpecific.java new file mode 100644 index 0000000..f954afb --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/JerseySpecific.java @@ -0,0 +1,166 @@ +package generators; + +import java.util.List; +import java.util.Map; + +import algorithms.TypeInference; +import code.ast.Annotation; +import code.ast.CompilationUnit; +import code.ast.FieldDeclaration; +import code.ast.ImportDeclaration; +import code.ast.MethodDeclaration; +import code.ast.TypeDeclaration; +import code.ast.VariableDeclaration; +import models.algebra.Type; +import models.dataConstraintModel.DataConstraintModel; + +public class JerseySpecific extends RestApiSpecific { + public static final Type typeClient = new Type("Client", "Client"); + + public JerseySpecific() { + langSpec = new JavaSpecific(); + } + + @Override + public void addComponentAnnotations(TypeDeclaration component, String resourcePath) { + component.addAnnotation(new Annotation("Component")); + component.addAnnotation(new Annotation("Path", "\"/" + resourcePath + "\"")); + } + + @Override + public void addGetAnnotations(MethodDeclaration getMethod) { + getMethod.addAnnotation(new Annotation("Produces", "MediaType.APPLICATION_JSON")); + getMethod.addAnnotation(new Annotation("GET")); + } + + @Override + public void addPutAnnotations(MethodDeclaration putMethod) { + putMethod.addAnnotation(new Annotation("PUT")); + } + + @Override + public void addPostAnnotations(MethodDeclaration postMethod) { + postMethod.addAnnotation(new Annotation("POST")); + } + + @Override + public void addDeleteAnnotations(MethodDeclaration deleteMethod) { + deleteMethod.addAnnotation(new Annotation("DELETE")); + } + + @Override + public void addPathAnnotation(MethodDeclaration method, String resourcePath) { + method.addAnnotation(new Annotation("Path", "\"" + resourcePath + "\"")); + } + + @Override + public void addPathParamAnnotation(VariableDeclaration var, String paramName) { + var.addAnnotation(new Annotation("PathParam", "\"" + paramName + "\"")); + } + + @Override + public void addFormParamAnnotation(VariableDeclaration var, String paramName) { + var.addAnnotation(new Annotation("FormParam", "\"" + paramName + "\"")); + } + + @Override + public void addPlatformSpecificImports(CompilationUnit cu) { + cu.addImport(new ImportDeclaration("javax.ws.rs.*")); + cu.addImport(new ImportDeclaration("javax.ws.rs.client.*")); + cu.addImport(new ImportDeclaration("javax.ws.rs.core.*")); + cu.addImport(new ImportDeclaration("org.springframework.stereotype.Component")); + cu.addImport(new ImportDeclaration("com.fasterxml.jackson.databind.ObjectMapper")); + cu.addImport(new ImportDeclaration("com.fasterxml.jackson.core.JsonProcessingException")); + } + + @Override + public boolean hasHttpClientFieldDeclaration(TypeDeclaration component) { + for (FieldDeclaration field: component.getFields()) { + if (field.getType().equals(typeClient)) { + return true; + } + } + return false; + } + + @Override + public void addHttpClientFieldDeclaration(TypeDeclaration component) { + FieldDeclaration clientField = new FieldDeclaration(typeClient, "client", "ClientBuilder.newClient()"); + component.addField(clientField); + } + + @Override + public String getConversionFromJsonString(String fromStrVarName, String toVarName, String toVarType) { + return toVarType + toVarName + langSpec.getAssignment() + langSpec.getConstructorInvocation("ObjectMapper", null) + ".readValue(" + fromStrVarName + ", HashMap.class)"; + } + + @Override + public String getHttpMethodParamsConstructionStatement(String callerResourceName, List>> params, boolean isFirstCall) { + String statements = ""; + if (isFirstCall) { + statements += "Form "; + } + statements += "form" + langSpec.getAssignment() + langSpec.getConstructorInvocation("Form", null) + langSpec.getStatementDelimiter() + "\n"; + for (Map.Entry> param: params) { + Type paramType = param.getKey(); + String paramName = param.getValue().getKey(); + String value = param.getValue().getValue(); + if (DataConstraintModel.typeList.isAncestorOf(paramType)) { + Type compType = TypeInference.getListComponentType(paramType); + String wrapperType = DataConstraintModel.getWrapperType(compType); + if (wrapperType == null) { + statements += langSpec.getForStatementForCollection("i", compType.getInterfaceTypeName(), value) + "\n"; + } else { + statements += langSpec.getForStatementForCollection("i", wrapperType, value) + "\n"; + } + if (DataConstraintModel.typeTuple.isAncestorOf(compType) || DataConstraintModel.typePair.isAncestorOf(paramType) || DataConstraintModel.typeList.isAncestorOf(compType) || DataConstraintModel.typeMap.isAncestorOf(paramType)) { + statements += "\tform.param(\"" + paramName + "\", " + langSpec.getConstructorInvocation("ObjectMapper", null) + ".writeValueAsString(i))" + langSpec.getStatementDelimiter() + "\n"; // typeTuple: {"1.0":2.0}, typePair: {"left": 1.0, "right":2.0} + } else { + statements += "\tform.param(\"" + paramName + "\", i.toString())" + langSpec.getStatementDelimiter() + "\n"; + } + statements += langSpec.getEndForStatement("i") + "\n"; +// return "Entity entity = Entity.entity(" + paramName + ".toString(), MediaType.APPLICATION_JSON);"; + } else if (DataConstraintModel.typeTuple.isAncestorOf(paramType) || DataConstraintModel.typePair.isAncestorOf(paramType) || DataConstraintModel.typeMap.isAncestorOf(paramType)) { + // typeTuple: {"1.0":2.0}, typePair: {"left": 1.0, "right":2.0} + statements += "form.param(\"" + paramName + "\", " + langSpec.getConstructorInvocation("ObjectMapper", null) + ".writeValueAsString(" + value + "))" + langSpec.getStatementDelimiter() + "\n"; + } else { + statements += "form.param(\"" + paramName + "\", " + new JavaSpecific().getValueToStringExp(paramType.getImplementationTypeName(), value) + ")" + langSpec.getStatementDelimiter() + "\n"; + } + } + if (isFirstCall) { + statements += "Entity "; + } + statements += "entity = Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED)" + langSpec.getStatementDelimiter(); + return statements; + } + + @Override + public String getHttpMethodCallStatement(String baseURL, String resourceName, String senderResName, String httpMethod) { + if (senderResName == null) { + return "client.target(\"" + baseURL + "\").path(\"/" + resourceName + "\").request()." + httpMethod + "(entity, String.class)" + langSpec.getStatementDelimiter(); + } else { + // For each source resource, a child resource is defined in the destination resource so that its state can be updated separately. + return "client.target(\"" + baseURL + "\").path(\"/" + resourceName + "/" + senderResName + "\").request()." + httpMethod + "(entity, String.class)" + langSpec.getStatementDelimiter(); + } + } + + @Override + public String getHttpMethodCallWithResponseStatement(String baseURL, String resourceName, String httpMethod, String responseTypeName) { + String responseShortTypeName = responseTypeName; + if (responseTypeName.contains("<")) { + responseShortTypeName = responseTypeName.substring(0, responseTypeName.indexOf("<")); + } + return "client.target(\"" + baseURL + "\").path(\"/" + resourceName + "\").request()." + httpMethod + "(" + responseShortTypeName + ".class)" + langSpec.getStatementDelimiter(); + } + + @Override + public void addJsonException(MethodDeclaration method) { + method.addThrow("JsonProcessingException"); + } + + @Override + public boolean hasJsonException(MethodDeclaration method) { + if (method.getThrows() == null || method.getThrows().getExceptions() == null) return false; + return method.getThrows().getExceptions().contains("JsonProcessingException"); + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/RestApiSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/RestApiSpecific.java new file mode 100644 index 0000000..3ddf549 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/RestApiSpecific.java @@ -0,0 +1,72 @@ +package generators; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map.Entry; + +import code.ast.Annotation; +import code.ast.CompilationUnit; +import code.ast.FieldDeclaration; +import code.ast.ImportDeclaration; +import code.ast.MethodDeclaration; +import code.ast.TypeDeclaration; +import code.ast.VariableDeclaration; +import models.algebra.Type; + +abstract public class RestApiSpecific implements IPlatformSpecific { + protected ILanguageSpecific langSpec = null; + + @Override + public boolean hasMain() { + return false; + } + + @Override + public boolean isMonolithic() { + return false; + } + + @Override + public boolean isDifferentTreesAsDifferentServices() { + return true; + } + + abstract public void addComponentAnnotations(TypeDeclaration component, String resourcePath); + + abstract public void addGetAnnotations(MethodDeclaration getMethod); + + abstract public void addPutAnnotations(MethodDeclaration putMethod); + + abstract public void addPostAnnotations(MethodDeclaration postMethod); + + abstract public void addDeleteAnnotations(MethodDeclaration deleteMethod); + + abstract public void addPathAnnotation(MethodDeclaration method, String resourcePath); + + abstract public void addPathParamAnnotation(VariableDeclaration var, String paramName); + + abstract public void addFormParamAnnotation(VariableDeclaration var, String paramName); + + abstract public void addPlatformSpecificImports(CompilationUnit cu); + + abstract public boolean hasHttpClientFieldDeclaration(TypeDeclaration component); + + abstract public void addHttpClientFieldDeclaration(TypeDeclaration component); + + abstract public String getConversionFromJsonString(String fromStrVarName, String toVarName, String toVarType); + + abstract public String getHttpMethodParamsConstructionStatement(String callerResourceName, List>> params, boolean isFirstCall); + + abstract public String getHttpMethodCallStatement(String baseURL, String resourceName, String senderResName, String httpMethod); + + abstract public String getHttpMethodCallWithResponseStatement(String baseURL, String resourceName, String httpMethod, String responseTypeName); + + abstract public void addJsonException(MethodDeclaration method); + + abstract public boolean hasJsonException(MethodDeclaration method); + + public String getBaseURL() { + return "http://localhost:8080"; + } + +} diff --git a/AlgebraicDataflowArchitectureModel/src/generators/StandaloneSpecific.java b/AlgebraicDataflowArchitectureModel/src/generators/StandaloneSpecific.java new file mode 100644 index 0000000..ce4acd5 --- /dev/null +++ b/AlgebraicDataflowArchitectureModel/src/generators/StandaloneSpecific.java @@ -0,0 +1,28 @@ +package generators; + +import java.util.List; + +import code.ast.Annotation; +import code.ast.CompilationUnit; +import code.ast.ImportDeclaration; +import code.ast.MethodDeclaration; +import code.ast.TypeDeclaration; +import code.ast.VariableDeclaration; + +public class StandaloneSpecific implements IPlatformSpecific { + + @Override + public boolean hasMain() { + return true; + } + + @Override + public boolean isMonolithic() { + return true; + } + + @Override + public boolean isDifferentTreesAsDifferentServices() { + return false; // meaningless + } +} diff --git a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java index 23a6c65..6ab539a 100644 --- a/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java +++ b/AlgebraicDataflowArchitectureModel/src/models/dataFlowModel/DataTransferChannel.java @@ -225,6 +225,18 @@ return deriveUpdateExpressionOf(targetMember, stateAccessor, null); } + /** + * Derive the state update calculation of the target channel member with a given resource push/pull state accessor. + * @param targetMember a channel member whose state is to be updated + * @param stateAccessor a push/pull resource state accessor + * @param inputResourceToStateAccessor push/pull resource state accessors (if null, stateAccessor is used.) + * @return the derived update calculation and the unified message + * @throws ParameterizedIdentifierIsFutureWork + * @throws ResolvingMultipleDefinitionIsFutureWork + * @throws InvalidMessage + * @throws UnificationFailed + * @throws ValueUndefined + */ public Map.Entry deriveUpdateExpressionOf(ChannelMember targetMember, IResourceStateAccessor stateAccessor, Map inputResourceToStateAccessor) throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { if (!getOutputChannelMembers().contains(targetMember)) return null; @@ -282,6 +294,18 @@ return fillOutsideResourcePaths(targetMember, stateAccessor, null).getKey(); } + /** + * Fill outside resource paths with a given resource push/pull state accessor. + * @param targetMember a channel member whose state is to be updated + * @param stateAccessor a push/pull resource state accessor + * @param inputResourceToStateAccessor push/pull resource state accessors (if null, stateAccessor is used.) + * @return map from a depending channel member to the pair of the filled resource path and the set of the depended channel members + * @throws ParameterizedIdentifierIsFutureWork + * @throws ResolvingMultipleDefinitionIsFutureWork + * @throws InvalidMessage + * @throws UnificationFailed + * @throws ValueUndefined + */ public Map.Entry>>, Term> fillOutsideResourcePaths(ChannelMember targetMember, IResourceStateAccessor stateAccessor, Map inputResourceToStateAccessor) throws ParameterizedIdentifierIsFutureWork, ResolvingMultipleDefinitionIsFutureWork, InvalidMessage, UnificationFailed, ValueUndefined { Map>> resourcePaths = new HashMap<>(); diff --git a/AlgebraicDataflowArchitectureModel/src/tests/JAXRSCodeGeneratorTest.java b/AlgebraicDataflowArchitectureModel/src/tests/JAXRSCodeGeneratorTest.java index f72baa9..9df8290 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/JAXRSCodeGeneratorTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/JAXRSCodeGeneratorTest.java @@ -23,11 +23,14 @@ import code.ast.MethodDeclaration; import code.ast.TypeDeclaration; import code.ast.VariableDeclaration; +import generators.CodeGeneratorFromDataFlowGraph; import generators.DataTransferMethodAnalyzer; import generators.JavaCodeGenerator; import generators.JavaMethodBodyGenerator; +import generators.JavaSpecific; import generators.JerseyCodeGenerator; import generators.JerseyMethodBodyGenerator; +import generators.JerseySpecific; import models.Edge; import models.dataFlowModel.*; import parser.*; @@ -146,7 +149,6 @@ Entry, // arg types Integer>>>>>>> // lines of code exprectedStructure = new HashMap<>(); - exprectedStructure.put("Hour", Map.entry(Set.of("@Path(\"/hour\")","@Component"), Map.entry(Map.ofEntries(Map.entry("value", "int")), Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), @@ -156,11 +158,18 @@ Map.entry("updateFromMin", Map.entry(Set.of("@POST"), Map.entry("void", Map.entry(List.of("int"), - 1)))), - Map.entry("Hour", Map.entry(Set.of(), - Map.entry("void", - Map.entry(List.of("int"), - 1)))))))); + 1)))))))); + exprectedStructure.put("Min", Map.entry(Set.of("@Path(\"/min\")","@Component"), + Map.entry(Map.ofEntries(Map.entry("value", "int"), + Map.entry("client", "Client")), + Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), + Map.entry("int", + Map.entry(List.of(), + 1)))), + Map.entry("tick", Map.entry(Set.of("@POST"), + Map.entry("void", + Map.entry(List.of(), + 3)))))))); exprectedStructure.put("Min_ang", Map.entry(Set.of("@Path(\"/min_ang\")","@Component"), Map.entry(Map.ofEntries(Map.entry("client", "Client")), Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), @@ -173,41 +182,13 @@ Map.entry("double", Map.entry(List.of(), 2)))))))); - exprectedStructure.put("Min", Map.entry(Set.of("@Path(\"/min\")","@Component"), - Map.entry(Map.ofEntries(Map.entry("value", "int"), - Map.entry("client", "Client")), - Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), - Map.entry("int", - Map.entry(List.of(), - 1)))), - Map.entry("Min", Map.entry(Set.of(), - Map.entry("void", - Map.entry(List.of("int"), - 1)))), - Map.entry("tick", Map.entry(Set.of("@POST"), - Map.entry("void", - Map.entry(List.of(), - 3)))))))); + checkStructure(generatedCode, exprectedStructure); // generateCheckCode(generatedCode); // check PUSH-first generatedCode = generateCode("models/Clock.model", PushPullValue.PUSH); exprectedStructure.clear(); - exprectedStructure.put("Min_ang", Map.entry(Set.of("@Path(\"/min_ang\")","@Component"), - Map.entry(Map.ofEntries(Map.entry("value", "double")), - Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), - Map.entry("double", - Map.entry(List.of(), - 1)))), - Map.entry("updateFromMin", Map.entry(Set.of("@PUT"), - Map.entry("void", - Map.entry(List.of("int"), - 1)))), - Map.entry("Min_ang", Map.entry(Set.of(), - Map.entry("void", - Map.entry(List.of("double"), - 1)))))))); exprectedStructure.put("Hour_ang", Map.entry(Set.of("@Path(\"/hour_ang\")","@Component"), Map.entry(Map.ofEntries(Map.entry("value", "double")), Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), @@ -217,26 +198,7 @@ Map.entry("updateFromHour", Map.entry(Set.of("@PUT"), Map.entry("void", Map.entry(List.of("int"), - 1)))), - Map.entry("Hour_ang", Map.entry(Set.of(), - Map.entry("void", - Map.entry(List.of("double"), - 1)))))))); - exprectedStructure.put("Min", Map.entry(Set.of("@Path(\"/min\")","@Component"), - Map.entry(Map.ofEntries(Map.entry("value", "int"), - Map.entry("client", "Client")), - Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), - Map.entry("int", - Map.entry(List.of(), - 1)))), - Map.entry("Min", Map.entry(Set.of(), - Map.entry("void", - Map.entry(List.of("int"), - 1)))), - Map.entry("tick", Map.entry(Set.of("@POST"), - Map.entry("void", - Map.entry(List.of(), - 5)))))))); + 1)))))))); exprectedStructure.put("Hour", Map.entry(Set.of("@Path(\"/hour\")","@Component"), Map.entry(Map.ofEntries(Map.entry("value", "int"), Map.entry("client", "Client")), @@ -247,11 +209,28 @@ Map.entry("updateFromMin", Map.entry(Set.of("@POST"), Map.entry("void", Map.entry(List.of("int"), - 3)))), - Map.entry("Hour", Map.entry(Set.of(), - Map.entry("void", - Map.entry(List.of("int"), - 1)))))))); + 3)))))))); + exprectedStructure.put("Min", Map.entry(Set.of("@Path(\"/min\")","@Component"), + Map.entry(Map.ofEntries(Map.entry("value", "int"), + Map.entry("client", "Client")), + Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), + Map.entry("int", + Map.entry(List.of(), + 1)))), + Map.entry("tick", Map.entry(Set.of("@POST"), + Map.entry("void", + Map.entry(List.of(), + 5)))))))); + exprectedStructure.put("Min_ang", Map.entry(Set.of("@Path(\"/min_ang\")","@Component"), + Map.entry(Map.ofEntries(Map.entry("value", "double")), + Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), + Map.entry("double", + Map.entry(List.of(), + 1)))), + Map.entry("updateFromMin", Map.entry(Set.of("@PUT"), + Map.entry("void", + Map.entry(List.of("int"), + 1)))))))); checkStructure(generatedCode, exprectedStructure); // generateCheckCode(generatedCode); @@ -947,6 +926,23 @@ Map.entry("int", Map.entry(List.of(), 2)))))))); + exprectedStructure.put("Total", Map.entry(Set.of("@Path(\"/total\")","@Component"), + Map.entry(Map.ofEntries(Map.entry("client", "Client")), + Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), + Map.entry("int", + Map.entry(List.of(), + 2)))))))); + exprectedStructure.put("Payment", Map.entry(Set.of("@Path(\"/payment\")","@Component"), + Map.entry(Map.ofEntries(Map.entry("value", "int"), + Map.entry("client", "Client")), + Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), + Map.entry("int", + Map.entry(List.of(), + 1)))), + Map.entry("purchase", Map.entry(Set.of("@PUT"), + Map.entry("void", + Map.entry(List.of("int"), + 3)))))))); exprectedStructure.put("History", Map.entry(Set.of("@Path(\"/history\")","@Component"), Map.entry(Map.ofEntries(Map.entry("value", "List")), Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), @@ -956,32 +952,7 @@ Map.entry("updateFromPayment", Map.entry(Set.of("@POST"), Map.entry("void", Map.entry(List.of("int"), - 1)))), - Map.entry("History", Map.entry(Set.of(), - Map.entry("void", - Map.entry(List.of("List"), - 1)))))))); - exprectedStructure.put("Payment", Map.entry(Set.of("@Path(\"/payment\")","@Component"), - Map.entry(Map.ofEntries(Map.entry("value", "int"), - Map.entry("client", "Client")), - Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), - Map.entry("int", - Map.entry(List.of(), - 1)))), - Map.entry("Payment", Map.entry(Set.of(), - Map.entry("void", - Map.entry(List.of("int"), - 1)))), - Map.entry("purchase", Map.entry(Set.of("@PUT"), - Map.entry("void", - Map.entry(List.of("int"), - 3)))))))); - exprectedStructure.put("Total", Map.entry(Set.of("@Path(\"/total\")","@Component"), - Map.entry(Map.ofEntries(Map.entry("client", "Client")), - Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), - Map.entry("int", - Map.entry(List.of(), - 2)))))))); + 1)))))))); checkStructure(generatedCode, exprectedStructure); // generateCheckCode(generatedCode); @@ -989,6 +960,17 @@ // check PUSH-first generatedCode = generateCode("models/POS.model", PushPullValue.PUSH); exprectedStructure.clear(); + exprectedStructure.put("Payment", Map.entry(Set.of("@Path(\"/payment\")","@Component"), + Map.entry(Map.ofEntries(Map.entry("value", "int"), + Map.entry("client", "Client")), + Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), + Map.entry("int", + Map.entry(List.of(), + 1)))), + Map.entry("purchase", Map.entry(Set.of("@PUT"), + Map.entry("void", + Map.entry(List.of("int"), + 5)))))))); exprectedStructure.put("Total", Map.entry(Set.of("@Path(\"/total\")","@Component"), Map.entry(Map.ofEntries(Map.entry("value", "int")), Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), @@ -998,11 +980,7 @@ Map.entry("updateFromHistory", Map.entry(Set.of("@PUT"), Map.entry("void", Map.entry(List.of("List"), - 1)))), - Map.entry("Total", Map.entry(Set.of(), - Map.entry("void", - Map.entry(List.of("int"), - 1)))))))); + 1)))))))); exprectedStructure.put("History", Map.entry(Set.of("@Path(\"/history\")","@Component"), Map.entry(Map.ofEntries(Map.entry("value", "List"), Map.entry("client", "Client")), @@ -1013,11 +991,7 @@ Map.entry("updateFromPayment", Map.entry(Set.of("@POST"), Map.entry("void", Map.entry(List.of("int"), - 3)))), - Map.entry("History", Map.entry(Set.of(), - Map.entry("void", - Map.entry(List.of("List"), - 1)))))))); + 3)))))))); exprectedStructure.put("Points", Map.entry(Set.of("@Path(\"/points\")","@Component"), Map.entry(Map.ofEntries(Map.entry("value", "int")), Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), @@ -1027,26 +1001,7 @@ Map.entry("updateFromPayment", Map.entry(Set.of("@PUT"), Map.entry("void", Map.entry(List.of("int"), - 1)))), - Map.entry("Points", Map.entry(Set.of(), - Map.entry("void", - Map.entry(List.of("int"), - 1)))))))); - exprectedStructure.put("Payment", Map.entry(Set.of("@Path(\"/payment\")","@Component"), - Map.entry(Map.ofEntries(Map.entry("value", "int"), - Map.entry("client", "Client")), - Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), - Map.entry("int", - Map.entry(List.of(), - 1)))), - Map.entry("Payment", Map.entry(Set.of(), - Map.entry("void", - Map.entry(List.of("int"), - 1)))), - Map.entry("purchase", Map.entry(Set.of("@PUT"), - Map.entry("void", - Map.entry(List.of("int"), - 5)))))))); + 1)))))))); checkStructure(generatedCode, exprectedStructure); // generateCheckCode(generatedCode); @@ -1145,11 +1100,7 @@ Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), Map.entry("Map", Map.entry(List.of(), - 8)))), - Map.entry("Counts", Map.entry(Set.of(), - Map.entry("void", - Map.entry(List.of("Map"), - 1)))))))); + 8)))))))); exprectedStructure.put("Account", Map.entry(Set.of(), Map.entry(Map.ofEntries(Map.entry("vote", "String")), Map.ofEntries(Map.entry("getValue", Map.entry(Set.of(), @@ -1178,22 +1129,22 @@ Map.entry("Account", Map.entry(List.of("String"), 1)))), - Map.entry("getAccountValue", Map.entry(Set.of("@Path(\"/{aid}\")","@Produces(MediaType.APPLICATION_JSON)","@GET"), - Map.entry("Map", - Map.entry(List.of("String"), - 1)))), Map.entry("getVoteValue", Map.entry(Set.of("@Path(\"/{aid}/vote\")","@Produces(MediaType.APPLICATION_JSON)","@GET"), Map.entry("String", Map.entry(List.of("String"), 1)))), - Map.entry("signUp", Map.entry(Set.of("@POST"), - Map.entry("void", - Map.entry(List.of("String","String"), - 1)))), + Map.entry("getAccountValue", Map.entry(Set.of("@Path(\"/{aid}\")","@Produces(MediaType.APPLICATION_JSON)","@GET"), + Map.entry("Map", + Map.entry(List.of("String"), + 1)))), Map.entry("cast", Map.entry(Set.of("@Path(\"/{aid}/vote\")","@PUT"), Map.entry("void", Map.entry(List.of("String","String"), - 1)))))))); + 1)))), + Map.entry("signUp", Map.entry(Set.of("@POST"), + Map.entry("void", + Map.entry(List.of("String","String"), + 1)))))))); checkStructure(generatedCode, exprectedStructure); // generateCheckCode(generatedCode); @@ -1219,6 +1170,12 @@ Entry, // arg types Integer>>>>>>> // lines of code exprectedStructure = new HashMap<>(); + exprectedStructure.put("Temp_c", Map.entry(Set.of("@Path(\"/temp_c\")","@Component"), + Map.entry(Map.ofEntries(Map.entry("client", "Client")), + Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), + Map.entry("double", + Map.entry(List.of(), + 2)))))))); exprectedStructure.put("Highest", Map.entry(Set.of("@Path(\"/highest\")","@Component"), Map.entry(Map.ofEntries(Map.entry("value", "double")), Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), @@ -1229,20 +1186,10 @@ Map.entry("void", Map.entry(List.of("double"), 1)))), - Map.entry("Highest", Map.entry(Set.of(), - Map.entry("void", - Map.entry(List.of("double"), - 1)))), Map.entry("reset", Map.entry(Set.of("@PUT"), Map.entry("void", Map.entry(List.of("double"), 1)))))))); - exprectedStructure.put("Temp_c", Map.entry(Set.of("@Path(\"/temp_c\")","@Component"), - Map.entry(Map.ofEntries(Map.entry("client", "Client")), - Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), - Map.entry("double", - Map.entry(List.of(), - 2)))))))); exprectedStructure.put("Temp_f", Map.entry(Set.of("@Path(\"/temp_f\")","@Component"), Map.entry(Map.ofEntries(Map.entry("value", "double"), Map.entry("client", "Client")), @@ -1250,10 +1197,6 @@ Map.entry("double", Map.entry(List.of(), 1)))), - Map.entry("Temp_f", Map.entry(Set.of(), - Map.entry("void", - Map.entry(List.of("double"), - 1)))), Map.entry("observe", Map.entry(Set.of("@PUT"), Map.entry("void", Map.entry(List.of("double"), @@ -1265,35 +1208,6 @@ // check PUSH-first generatedCode = generateCode("models/WeatherObservationSystem.model", PushPullValue.PUSH); exprectedStructure.clear(); - exprectedStructure.put("Temp_c", Map.entry(Set.of("@Path(\"/temp_c\")","@Component"), - Map.entry(Map.ofEntries(Map.entry("value", "double")), - Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), - Map.entry("double", - Map.entry(List.of(), - 1)))), - Map.entry("updateFromTemp_f", Map.entry(Set.of("@PUT"), - Map.entry("void", - Map.entry(List.of("double"), - 1)))), - Map.entry("Temp_c", Map.entry(Set.of(), - Map.entry("void", - Map.entry(List.of("double"), - 1)))))))); - exprectedStructure.put("Temp_f", Map.entry(Set.of("@Path(\"/temp_f\")","@Component"), - Map.entry(Map.ofEntries(Map.entry("value", "double"), - Map.entry("client", "Client")), - Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), - Map.entry("double", - Map.entry(List.of(), - 1)))), - Map.entry("Temp_f", Map.entry(Set.of(), - Map.entry("void", - Map.entry(List.of("double"), - 1)))), - Map.entry("observe", Map.entry(Set.of("@PUT"), - Map.entry("void", - Map.entry(List.of("double"), - 5)))))))); exprectedStructure.put("Highest", Map.entry(Set.of("@Path(\"/highest\")","@Component"), Map.entry(Map.ofEntries(Map.entry("value", "double")), Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), @@ -1304,14 +1218,31 @@ Map.entry("void", Map.entry(List.of("double"), 1)))), - Map.entry("Highest", Map.entry(Set.of(), - Map.entry("void", - Map.entry(List.of("double"), - 1)))), Map.entry("reset", Map.entry(Set.of("@PUT"), Map.entry("void", Map.entry(List.of("double"), 1)))))))); + exprectedStructure.put("Temp_f", Map.entry(Set.of("@Path(\"/temp_f\")","@Component"), + Map.entry(Map.ofEntries(Map.entry("value", "double"), + Map.entry("client", "Client")), + Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), + Map.entry("double", + Map.entry(List.of(), + 1)))), + Map.entry("observe", Map.entry(Set.of("@PUT"), + Map.entry("void", + Map.entry(List.of("double"), + 5)))))))); + exprectedStructure.put("Temp_c", Map.entry(Set.of("@Path(\"/temp_c\")","@Component"), + Map.entry(Map.ofEntries(Map.entry("value", "double")), + Map.ofEntries(Map.entry("getValue", Map.entry(Set.of("@Produces(MediaType.APPLICATION_JSON)","@GET"), + Map.entry("double", + Map.entry(List.of(), + 1)))), + Map.entry("updateFromTemp_f", Map.entry(Set.of("@PUT"), + Map.entry("void", + Map.entry(List.of("double"), + 1)))))))); checkStructure(generatedCode, exprectedStructure); // generateCheckCode(generatedCode); @@ -1346,6 +1277,7 @@ TypeInference.infer(model); DataTransferMethodAnalyzer.decideToStoreResourceStates(graph); ArrayList codetree = JerseyMethodBodyGenerator.doGenerate(graph, model, JerseyCodeGenerator.doGenerate(graph, model)); +// ArrayList codetree = new CodeGeneratorFromDataFlowGraph().generateCode(model, graph, new JerseySpecific(), new JavaSpecific()); return codetree; } @@ -1393,7 +1325,7 @@ if (expectedFieldType.equals("void")) { assertNull(generatedField.getType()); } else { - assertEquals(generatedField.getType().getInterfaceTypeName(), expectedFieldType); + assertEquals(expectedFieldType, generatedField.getType().getInterfaceTypeName()); } } @@ -1422,12 +1354,12 @@ String expectedReturnType = expectedMethodSignature.getKey(); if (expectedReturnType.equals("void")) { if (generatedMethod.getReturnType() != null) { - assertEquals(generatedMethod.getReturnType().getInterfaceTypeName(), expectedReturnType); + assertEquals(expectedReturnType, generatedMethod.getReturnType().getInterfaceTypeName()); } else { assertNull(generatedMethod.getReturnType()); } } else { - assertEquals(generatedMethod.getReturnType().getInterfaceTypeName(), expectedReturnType); + assertEquals(expectedReturnType, generatedMethod.getReturnType().getInterfaceTypeName()); } Entry, Integer> expectedMethodInfo2 = expectedMethodSignature.getValue(); List expectedArgTypes = expectedMethodInfo2.getKey(); @@ -1441,7 +1373,7 @@ assertTrue(existsArg); } int expectedLinesOfCode = expectedMethodInfo2.getValue(); - assertEquals(generatedMethod.getBody().getStatements().size(), expectedLinesOfCode); + assertEquals(expectedLinesOfCode, generatedMethod.getBody().getStatements().size()); } } } diff --git a/AlgebraicDataflowArchitectureModel/src/tests/JavaCodeGeneratorTest.java b/AlgebraicDataflowArchitectureModel/src/tests/JavaCodeGeneratorTest.java index d9e266f..b9a5dc0 100644 --- a/AlgebraicDataflowArchitectureModel/src/tests/JavaCodeGeneratorTest.java +++ b/AlgebraicDataflowArchitectureModel/src/tests/JavaCodeGeneratorTest.java @@ -25,6 +25,7 @@ import generators.JavaCodeGenerator; import generators.JavaMethodBodyGenerator; import generators.JavaSpecific; +import generators.StandaloneSpecific; import models.Edge; import models.dataFlowModel.*; import parser.*; @@ -55,7 +56,7 @@ testGroupChat(); testInventoryManagement(); // testOnlineBattleGame(); // A feature has not been implemented for Java prototype generation. - testOnlineBattleGame2(); // Two methods with the same signature are generated. + testOnlineBattleGame2(); // Two methods with the same signature are generated. PUSH-first implementation still does not work. testPOS(); testSimpleTwitter(); testVotingSystem(); @@ -271,8 +272,7 @@ private void testCustomerManagement() { try { - // check PULL-first - ArrayList generatedCode = generateCode("models/CustomerManagement.model", PushPullValue.PULL); + ArrayList generatedCode = generateCode("models/CustomerManagement.model", null); Map, // field name to type Map", - Map.entry(List.of("String"), - 1))), - Map.entry("getCompany", Map.entry("Map", - Map.entry(List.of("String"), - 1))), - Map.entry("getAddress", Map.entry("String", - Map.entry(List.of("String"), - 1))), - Map.entry("getOrganization", Map.entry("String", - Map.entry(List.of("String"), - 1))), - Map.entry("setOrganization", Map.entry("void", - Map.entry(List.of("String","String"), - 1))), -// Map.entry("getAddress", Map.entry("String", -// Map.entry(List.of("String"), -// 1))), - Map.entry("setAddress", Map.entry("void", - Map.entry(List.of("String","String"), - 1))), - Map.entry("getCompanies", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("addCampany", Map.entry("void", - Map.entry(List.of("String","String"), - 1))), - Map.entry("getCustomers", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("addCustomer", Map.entry("void", - Map.entry(List.of("String","String"), - 1)))))); - exprectedStructure.put("Customer", Map.entry(Map.ofEntries(Map.entry("company", "Company"), - Map.entry("companies", "Companies"), - Map.entry("organization", "String")), - Map.ofEntries(Map.entry("getValue", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("getAddress", Map.entry("String", - Map.entry(List.of(), - 1))), - Map.entry("getOrganization", Map.entry("String", - Map.entry(List.of(), - 1))), - Map.entry("updateAddressFromOrganization", Map.entry("void", - Map.entry(List.of("String","String","String"), - 2))), - Map.entry("setOrganization", Map.entry("void", - Map.entry(List.of("String","String"), - 4))), - Map.entry("Customer", Map.entry("void", - Map.entry(List.of("Companies","String"), - 3)))))); - exprectedStructure.put("Company", Map.entry(Map.ofEntries(), - Map.ofEntries(Map.entry("getValue", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("getAddress", Map.entry("String", - Map.entry(List.of(), - 1))), - Map.entry("setAddress", Map.entry("void", - Map.entry(List.of("String","String"), - 1))), - Map.entry("Company", Map.entry("void", - Map.entry(List.of("String"), - 1)))))); - exprectedStructure.put("Companies", Map.entry(Map.ofEntries(), - Map.ofEntries(Map.entry("getValue", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("getCompany", Map.entry("Company", - Map.entry(List.of("String"), - 1))), - Map.entry("addCampany", Map.entry("void", - Map.entry(List.of("String","String"), - 1)))))); - exprectedStructure.put("Customers", Map.entry(Map.ofEntries(Map.entry("value", "Map"), - Map.entry("companies", "Companies")), - Map.ofEntries(Map.entry("getValue", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("getCustomer", Map.entry("Customer", - Map.entry(List.of("String"), - 1))), - Map.entry("addCustomer", Map.entry("void", - Map.entry(List.of("String","String"), - 1))), - Map.entry("Customers", Map.entry("void", - Map.entry(List.of("Companies"), - 1)))))); - - checkStructure(generatedCode, exprectedStructure); -// generateCheckCode(generatedCode); } catch (FileNotFoundException | ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefOrSubKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression @@ -490,8 +387,7 @@ private void testGroupChat() { try { - // check PULL-first - ArrayList generatedCode = generateCode("models/GroupChat.model", PushPullValue.PULL); + ArrayList generatedCode = generateCode("models/GroupChat.model", null); Map, // field name to type Map, // arg types Integer>>>>> // lines of code exprectedStructure = new HashMap<>(); - exprectedStructure.put("Main", Map.entry(Map.ofEntries(Map.entry("groups", "Groups"), - Map.entry("accounts", "Accounts")), + exprectedStructure.put("Main", Map.entry(Map.ofEntries(Map.entry("accounts", "Accounts"), + Map.entry("groups", "Groups")), Map.ofEntries(Map.entry("Main", Map.entry("void", Map.entry(List.of(), 2))), - Map.entry("getAccount", Map.entry("Map", - Map.entry(List.of("String"), - 1))), - Map.entry("getMessages", Map.entry("List", - Map.entry(List.of("String"), - 1))), - Map.entry("postMessage", Map.entry("void", - Map.entry(List.of("String","String"), - 1))), - Map.entry("getNotifications", Map.entry("Map", - Map.entry(List.of("String"), - 1))), - Map.entry("hasRead", Map.entry("void", - Map.entry(List.of("String","String"), - 1))), Map.entry("getAccounts", Map.entry("Map", Map.entry(List.of(), 1))), Map.entry("signUp", Map.entry("void", Map.entry(List.of("String"), 1))), + Map.entry("getGroup", Map.entry("Map", + Map.entry(List.of("String"), + 1))), + Map.entry("getMessages", Map.entry("List", + Map.entry(List.of("String"), + 1))), + Map.entry("postMessage", Map.entry("void", + Map.entry(List.of("String","String"), + 1))), + Map.entry("getAccount", Map.entry("Map", + Map.entry(List.of("String"), + 1))), + Map.entry("getMember", Map.entry("String", + Map.entry(List.of("String","int"), + 1))), + Map.entry("getNotifications", Map.entry("Map", + Map.entry(List.of("String"), + 1))), + Map.entry("hasRead", Map.entry("void", + Map.entry(List.of("String","String"), + 1))), Map.entry("getMembers", Map.entry("List", Map.entry(List.of("String"), 1))), Map.entry("addGroupMember", Map.entry("void", Map.entry(List.of("String","String"), 1))), - Map.entry("getGroup", Map.entry("Map", - Map.entry(List.of("String"), - 1))), - Map.entry("getMember", Map.entry("String", - Map.entry(List.of("String","int"), - 1))), Map.entry("getGroups", Map.entry("Map", Map.entry(List.of(), 1))), Map.entry("createGroup", Map.entry("void", Map.entry(List.of("String"), 1)))))); - exprectedStructure.put("Account", Map.entry(Map.ofEntries(), - Map.ofEntries(Map.entry("getValue", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("getNotifications", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("updateNotificationsFromMessages", Map.entry("void", - Map.entry(List.of("String","int","List","String"), - 1))), - Map.entry("hasRead", Map.entry("void", - Map.entry(List.of("String","String"), - 1))), - Map.entry("Account", Map.entry("void", - Map.entry(List.of("Map"), - 1)))))); exprectedStructure.put("Accounts", Map.entry(Map.ofEntries(), Map.ofEntries(Map.entry("getValue", Map.entry("Map", Map.entry(List.of(), @@ -569,22 +449,22 @@ Map.entry("signUp", Map.entry("void", Map.entry(List.of("String"), 1)))))); - exprectedStructure.put("Group", Map.entry(Map.ofEntries(Map.entry("members", "List"), - Map.entry("messages", "List"), + exprectedStructure.put("Group", Map.entry(Map.ofEntries(Map.entry("messages", "List"), Map.entry("account", "Account"), - Map.entry("accounts", "Accounts")), + Map.entry("accounts", "Accounts"), + Map.entry("members", "List")), Map.ofEntries(Map.entry("getValue", Map.entry("Map", Map.entry(List.of(), 1))), Map.entry("getMessages", Map.entry("List", Map.entry(List.of(), 1))), - Map.entry("getMembers", Map.entry("List", - Map.entry(List.of(), - 1))), Map.entry("getMember", Map.entry("String", Map.entry(List.of("int"), 1))), + Map.entry("getMembers", Map.entry("List", + Map.entry(List.of(), + 1))), Map.entry("postMessage", Map.entry("void", Map.entry(List.of("String","String"), 6))), @@ -594,7 +474,24 @@ Map.entry("Group", Map.entry("void", Map.entry(List.of("List","Accounts","List"), 3)))))); - exprectedStructure.put("Groups", Map.entry(Map.ofEntries(), + exprectedStructure.put("Account", Map.entry(Map.ofEntries(), + Map.ofEntries(Map.entry("getValue", Map.entry("Map", + Map.entry(List.of(), + 1))), + Map.entry("getNotifications", Map.entry("Map", + Map.entry(List.of(), + 1))), + Map.entry("updateNotificationsFromMessages", Map.entry("void", + Map.entry(List.of("String","String","int","List","String"), + 1))), + Map.entry("hasRead", Map.entry("void", + Map.entry(List.of("String","String"), + 1))), + Map.entry("Account", Map.entry("void", + Map.entry(List.of("Map"), + 1)))))); + exprectedStructure.put("Groups", Map.entry(Map.ofEntries(Map.entry("value", "Map"), + Map.entry("accounts", "Accounts")), Map.ofEntries(Map.entry("getValue", Map.entry("Map", Map.entry(List.of(), 1))), @@ -603,122 +500,13 @@ 1))), Map.entry("createGroup", Map.entry("void", Map.entry(List.of("String"), - 1)))))); + 1))), + Map.entry("Groups", Map.entry("void", + Map.entry(List.of("Accounts"), + 1)))))); checkStructure(generatedCode, exprectedStructure); // generateCheckCode(generatedCode); - - // check PUSH-first - generatedCode = generateCode("models/GroupChat.model", PushPullValue.PUSH); - exprectedStructure.clear(); - exprectedStructure.put("Main", Map.entry(Map.ofEntries(Map.entry("accounts", "Accounts"), - Map.entry("groups", "Groups")), - Map.ofEntries(Map.entry("Main", Map.entry("void", - Map.entry(List.of(), - 2))), - Map.entry("getMessages", Map.entry("List", - Map.entry(List.of("String"), - 1))), - Map.entry("postMessage", Map.entry("void", - Map.entry(List.of("String","String"), - 1))), - Map.entry("getGroup", Map.entry("Map", - Map.entry(List.of("String"), - 1))), - Map.entry("getAccounts", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("signUp", Map.entry("void", - Map.entry(List.of("String"), - 1))), - Map.entry("getAccount", Map.entry("Map", - Map.entry(List.of("String"), - 1))), - Map.entry("getNotifications", Map.entry("Map", - Map.entry(List.of("String"), - 1))), - Map.entry("hasRead", Map.entry("void", - Map.entry(List.of("String","String"), - 1))), - Map.entry("getGroups", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("createGroup", Map.entry("void", - Map.entry(List.of("String"), - 1))), - Map.entry("getMembers", Map.entry("List", - Map.entry(List.of("String"), - 1))), - Map.entry("addGroupMember", Map.entry("void", - Map.entry(List.of("String","String"), - 1))), - Map.entry("getMember", Map.entry("String", - Map.entry(List.of("String","int"), - 1)))))); - exprectedStructure.put("Group", Map.entry(Map.ofEntries(Map.entry("members", "List"), - Map.entry("messages", "List"), - Map.entry("account", "Account"), - Map.entry("accounts", "Accounts")), - Map.ofEntries(Map.entry("getValue", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("getMessages", Map.entry("List", - Map.entry(List.of(), - 1))), - Map.entry("getMembers", Map.entry("List", - Map.entry(List.of(), - 1))), - Map.entry("getMember", Map.entry("String", - Map.entry(List.of("int"), - 1))), - Map.entry("postMessage", Map.entry("void", - Map.entry(List.of("String","String"), - 6))), - Map.entry("addGroupMember", Map.entry("void", - Map.entry(List.of("String","String"), - 1))), - Map.entry("Group", Map.entry("void", - Map.entry(List.of("List","Accounts","List"), - 3)))))); - exprectedStructure.put("Accounts", Map.entry(Map.ofEntries(), - Map.ofEntries(Map.entry("getValue", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("getAccount", Map.entry("Account", - Map.entry(List.of("String"), - 1))), - Map.entry("signUp", Map.entry("void", - Map.entry(List.of("String"), - 1)))))); - exprectedStructure.put("Account", Map.entry(Map.ofEntries(), - Map.ofEntries(Map.entry("getValue", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("getNotifications", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("updateNotificationsFromMessages", Map.entry("void", - Map.entry(List.of("String","int","List","String"), - 1))), - Map.entry("hasRead", Map.entry("void", - Map.entry(List.of("String","String"), - 1))), - Map.entry("Account", Map.entry("void", - Map.entry(List.of("Map"), - 1)))))); - exprectedStructure.put("Groups", Map.entry(Map.ofEntries(), - Map.ofEntries(Map.entry("getValue", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("getGroup", Map.entry("Group", - Map.entry(List.of("String"), - 1))), - Map.entry("createGroup", Map.entry("void", - Map.entry(List.of("String"), - 1)))))); - - checkStructure(generatedCode, exprectedStructure); -// generateCheckCode(generatedCode); } catch (FileNotFoundException | ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefOrSubKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression @@ -1055,8 +843,7 @@ private void testOnlineBattleGame2() { try { - // check PULL-first - ArrayList generatedCode = generateCode("models/OnlineBattleGame2.model", PushPullValue.PULL); + ArrayList generatedCode = generateCode("models/OnlineBattleGame2.model", null); Map, // field name to type Map", - Map.entry(List.of("String"), - 1))), - Map.entry("addRoomMember", Map.entry("void", - Map.entry(List.of("String","String"), - 1))), - Map.entry("getRoom", Map.entry("Map", - Map.entry(List.of("String"), - 1))), - Map.entry("getBattle", Map.entry("boolean", - Map.entry(List.of("String"), - 1))), - Map.entry("battle", Map.entry("void", - Map.entry(List.of("String","boolean"), - 1))), - Map.entry("getName", Map.entry("String", - Map.entry(List.of("String","int"), - 1))), - Map.entry("getId", Map.entry("String", - Map.entry(List.of("String","int"), - 1))), - Map.entry("getAccount", Map.entry("Map", - Map.entry(List.of("String"), - 1))), - Map.entry("getPoint", Map.entry("int", - Map.entry(List.of("String"), - 1))), - Map.entry("getAccounts", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("signUp", Map.entry("void", - Map.entry(List.of("String","String"), - 1))), - Map.entry("getRooms", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("createRoom", Map.entry("void", - Map.entry(List.of("String"), - 1))), - Map.entry("getMember", Map.entry("Map", - Map.entry(List.of("String","int"), - 1))), -// Map.entry("getName", Map.entry("String", -// Map.entry(List.of("String"), -// 1))), - Map.entry("changeName", Map.entry("void", - Map.entry(List.of("String","String"), - 1)))))); - exprectedStructure.put("Members", Map.entry(Map.ofEntries(), - Map.ofEntries(Map.entry("getValue", Map.entry("List", - Map.entry(List.of(), - 1))), - Map.entry("getMember", Map.entry("Member", - Map.entry(List.of("int"), - 1))), - Map.entry("addRoomMember", Map.entry("void", - Map.entry(List.of("String","String"), - 1)))))); - exprectedStructure.put("Room", Map.entry(Map.ofEntries(Map.entry("members", "Members"), - Map.entry("battle", "boolean"), - Map.entry("account", "Account"), - Map.entry("accounts", "Accounts")), - Map.ofEntries(Map.entry("getValue", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("getMembers", Map.entry("Members", - Map.entry(List.of(), - 1))), - Map.entry("getBattle", Map.entry("boolean", - Map.entry(List.of(), - 1))), - Map.entry("battle", Map.entry("void", - Map.entry(List.of("String","boolean"), - 6))), - Map.entry("Room", Map.entry("void", - Map.entry(List.of("boolean","Accounts"), - 2)))))); - exprectedStructure.put("Account", Map.entry(Map.ofEntries(Map.entry("point", "int"), - Map.entry("name", "String")), - Map.ofEntries(Map.entry("getValue", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("getPoint", Map.entry("int", - Map.entry(List.of(), - 1))), - Map.entry("getName", Map.entry("String", - Map.entry(List.of(), - 1))), - Map.entry("updatePointFromBattle", Map.entry("void", - Map.entry(List.of("String","String","int","boolean","String"), - 1))), - Map.entry("changeName", Map.entry("void", - Map.entry(List.of("String","String"), - 1))), - Map.entry("Account", Map.entry("void", - Map.entry(List.of("int","String"), - 2)))))); - exprectedStructure.put("Accounts", Map.entry(Map.ofEntries(), - Map.ofEntries(Map.entry("getValue", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("getAccount", Map.entry("Account", - Map.entry(List.of("String"), - 1))), - Map.entry("signUp", Map.entry("void", - Map.entry(List.of("String","String"), - 1)))))); - exprectedStructure.put("Rooms", Map.entry(Map.ofEntries(Map.entry("value", "Map"), - Map.entry("accounts", "Accounts")), - Map.ofEntries(Map.entry("getValue", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("getRoom", Map.entry("Room", - Map.entry(List.of("String"), - 1))), - Map.entry("createRoom", Map.entry("void", - Map.entry(List.of("String"), - 1))), - Map.entry("Rooms", Map.entry("void", - Map.entry(List.of("Accounts"), - 1)))))); - exprectedStructure.put("Member", Map.entry(Map.ofEntries(Map.entry("account", "Account"), - Map.entry("accounts", "Accounts"), - Map.entry("id", "String")), - Map.ofEntries(Map.entry("getValue", Map.entry("Map", - Map.entry(List.of(), - 1))), - Map.entry("getName", Map.entry("String", - Map.entry(List.of(), - 1))), - Map.entry("getId", Map.entry("String", - Map.entry(List.of(), - 1))), - Map.entry("updateNameFromId", Map.entry("void", - Map.entry(List.of("String","int","String","int","String"), - 2))), - Map.entry("Member", Map.entry("void", - Map.entry(List.of("Accounts","String"), - 2)))))); - - checkStructure(generatedCode, exprectedStructure); -// generateCheckCode(generatedCode); } catch (FileNotFoundException | ExpectedChannel | ExpectedChannelName | ExpectedLeftCurlyBracket | ExpectedInOrOutOrRefOrSubKeyword | ExpectedStateTransition | ExpectedEquals | ExpectedRHSExpression | WrongLHSExpression @@ -1602,12 +1238,12 @@ Map.entry("cast", Map.entry("void", Map.entry(List.of("String","String"), 1))), - Map.entry("getCounts", Map.entry("Map", - Map.entry(List.of(), - 1))), Map.entry("getAccount", Map.entry("Map", Map.entry(List.of("String"), - 1)))))); + 1))), + Map.entry("getCounts", Map.entry("Map", + Map.entry(List.of(), + 1)))))); exprectedStructure.put("Accounts", Map.entry(Map.ofEntries(), Map.ofEntries(Map.entry("getValue", Map.entry("Map", Map.entry(List.of(), @@ -1618,15 +1254,6 @@ Map.entry("signUp", Map.entry("void", Map.entry(List.of("String","String"), 1)))))); - exprectedStructure.put("Counts", Map.entry(Map.ofEntries(Map.entry("value", "Map"), - Map.entry("account", "Account"), - Map.entry("accounts", "Accounts")), - Map.ofEntries(Map.entry("getValue", Map.entry("Map", - Map.entry(List.of(), - 6))), - Map.entry("Counts", Map.entry("void", - Map.entry(List.of("Accounts"), - 1)))))); exprectedStructure.put("Account", Map.entry(Map.ofEntries(), Map.ofEntries(Map.entry("getValue", Map.entry("Map", Map.entry(List.of(), @@ -1640,6 +1267,15 @@ Map.entry("Account", Map.entry("void", Map.entry(List.of("String"), 1)))))); + exprectedStructure.put("Counts", Map.entry(Map.ofEntries(Map.entry("value", "Map"), + Map.entry("account", "Account"), + Map.entry("accounts", "Accounts")), + Map.ofEntries(Map.entry("getValue", Map.entry("Map", + Map.entry(List.of(), + 6))), + Map.entry("Counts", Map.entry("void", + Map.entry(List.of("Accounts"), + 1)))))); checkStructure(generatedCode, exprectedStructure); // generateCheckCode(generatedCode); @@ -1803,7 +1439,7 @@ TypeInference.infer(model); DataTransferMethodAnalyzer.decideToStoreResourceStates(graph); ArrayList codetree = JavaMethodBodyGenerator.doGenerate(graph, model, JavaCodeGenerator.doGenerate(graph, model)); -// ArrayList codetree = new CodeGeneratorFromDataFlowGraph().generateCode(model, graph, new JavaSpecific()); +// ArrayList codetree = new CodeGeneratorFromDataFlowGraph().generateCode(model, graph, new StandaloneSpecific(), new JavaSpecific()); return codetree; } @@ -1840,7 +1476,7 @@ if (expectedFieldType.equals("void")) { assertNull(generatedField.getType()); } else { - assertEquals(generatedField.getType().getInterfaceTypeName(), expectedFieldType); + assertEquals(expectedFieldType, generatedField.getType().getInterfaceTypeName()); } } @@ -1858,12 +1494,12 @@ String expectedReturnType = expectedMethodInfo.getKey(); if (expectedReturnType.equals("void")) { if (generatedMethod.getReturnType() != null) { - assertEquals(generatedMethod.getReturnType().getInterfaceTypeName(), expectedReturnType); + assertEquals(expectedReturnType, generatedMethod.getReturnType().getInterfaceTypeName()); } else { assertNull(generatedMethod.getReturnType()); } } else { - assertEquals(generatedMethod.getReturnType().getInterfaceTypeName(), expectedReturnType); + assertEquals(expectedReturnType, generatedMethod.getReturnType().getInterfaceTypeName()); } Entry, Integer> expectedMethodInfo2 = expectedMethodInfo.getValue(); List expectedArgTypes = expectedMethodInfo2.getKey(); @@ -1877,7 +1513,7 @@ assertTrue(existsArg); } int expectedLinesOfCode = expectedMethodInfo2.getValue(); - assertEquals(generatedMethod.getBody().getStatements().size(), expectedLinesOfCode); + assertEquals(expectedLinesOfCode, generatedMethod.getBody().getStatements().size()); } } }