Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrik Rentz-Reichert2012-12-04 10:18:24 +0000
committerHenrik Rentz-Reichert2012-12-04 10:18:24 +0000
commit73b4a1693e646cffb9691ccd231801e961bb9257 (patch)
tree6ad1f13c02f3daaa9b0b9a4642243d5ce459f3ff
parenta184bc763fdb00a1b129c4d6b564e1125d8a8f94 (diff)
downloadorg.eclipse.etrice-73b4a1693e646cffb9691ccd231801e961bb9257.tar.gz
org.eclipse.etrice-73b4a1693e646cffb9691ccd231801e961bb9257.tar.xz
org.eclipse.etrice-73b4a1693e646cffb9691ccd231801e961bb9257.zip
[core.room, core.room.tests] let ports with derived protocols connect
added validation for this case and test cases for the validation
-rw-r--r--plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/room/util/RoomHelpers.java20
-rw-r--r--plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/validation/RoomJavaValidator.java33
-rw-r--r--plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/validation/ValidationUtil.java70
-rw-r--r--tests/org.eclipse.etrice.core.room.tests/models/TestBindings.room104
-rw-r--r--tests/org.eclipse.etrice.core.room.tests/src/org/eclipse/etrice/core/TestBindings.java83
5 files changed, 308 insertions, 2 deletions
diff --git a/plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/room/util/RoomHelpers.java b/plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/room/util/RoomHelpers.java
index 125855a98..73a54316f 100644
--- a/plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/room/util/RoomHelpers.java
+++ b/plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/room/util/RoomHelpers.java
@@ -1332,4 +1332,24 @@ public class RoomHelpers {
return null;
}
+
+ /**
+ * checks whether pc1 is derived from (but not equal) pc2
+ *
+ * @param pc1 potential sub class
+ * @param pc2 potential super class
+ *
+ * @return true if pc1 is derived from pc2
+ */
+ public static boolean isDerivedFrom(ProtocolClass pc1, ProtocolClass pc2) {
+ if (pc1==pc2)
+ return false;
+
+ while (pc1!=null) {
+ if (pc1==pc2)
+ return true;
+ pc1 = pc1.getBase();
+ }
+ return false;
+ }
}
diff --git a/plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/validation/RoomJavaValidator.java b/plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/validation/RoomJavaValidator.java
index e02320001..24009a3dd 100644
--- a/plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/validation/RoomJavaValidator.java
+++ b/plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/validation/RoomJavaValidator.java
@@ -389,6 +389,9 @@ public class RoomJavaValidator extends AbstractRoomJavaValidator {
@Check
public void checkProtocol(ProtocolClass pc) {
+ if (ValidationUtil.isCircularClassHierarchy(pc))
+ return;
+
switch (pc.getCommType()) {
case DATA_DRIVEN:
if (pc.getBase()!=null && pc.getBase().getCommType()!=CommunicationType.DATA_DRIVEN)
@@ -409,6 +412,36 @@ public class RoomJavaValidator extends AbstractRoomJavaValidator {
break;
default:
}
+
+ if (pc.getBase()!=null) {
+ // derived protocol
+ if (pc.getIncomingMessages().size()>0 && pc.getOutgoingMessages().size()>0)
+ warning("a derived protocol should add either incoming or outgoing messages, not both", RoomPackage.Literals.PROTOCOL_CLASS__OUTGOING_MESSAGES);
+
+ {
+ List<Message> incoming = RoomHelpers.getAllMessages(pc, true);
+ HashSet<String> inNames = new HashSet<String>();
+ for (Message in : incoming) {
+ if (!inNames.add(in.getName())) {
+ int idx = pc.getIncomingMessages().indexOf(in);
+ if (idx>=0)
+ error("duplicate message name", pc, RoomPackage.Literals.PROTOCOL_CLASS__INCOMING_MESSAGES, idx);
+ }
+ }
+ }
+
+ {
+ List<Message> outgoing = RoomHelpers.getAllMessages(pc, true);
+ HashSet<String> outNames = new HashSet<String>();
+ for (Message out : outgoing) {
+ if (!outNames.add(out.getName())) {
+ int idx = pc.getOutgoingMessages().indexOf(out);
+ if (idx>=0)
+ error("duplicate message name", pc, RoomPackage.Literals.PROTOCOL_CLASS__OUTGOING_MESSAGES, idx);
+ }
+ }
+ }
+ }
}
@Check
diff --git a/plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/validation/ValidationUtil.java b/plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/validation/ValidationUtil.java
index 9a7340e42..7d3692854 100644
--- a/plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/validation/ValidationUtil.java
+++ b/plugins/org.eclipse.etrice.core.room/src/org/eclipse/etrice/core/validation/ValidationUtil.java
@@ -286,6 +286,10 @@ public class ValidationUtil {
return Result.error("ports are already bound");
// check protocol compatibility
+ boolean pc1extendsIncoming = false;
+ boolean pc1extendsOutgoing = false;
+ boolean pc2extendsIncoming = false;
+ boolean pc2extendsOutgoing = false;
{
GeneralProtocolClass pc1 = p1.getProtocol();
GeneralProtocolClass pc2 = p2.getProtocol();
@@ -315,8 +319,32 @@ public class ValidationUtil {
}
}
else {
- if (pc1!=pc2)
- return Result.error("protocols don't match");
+ if (pc1!=pc2) {
+ if (compoundInvolved) {
+ return Result.error("protocols don't match");
+ }
+ else {
+ if (RoomHelpers.isDerivedFrom((ProtocolClass)pc1, (ProtocolClass)pc2)) {
+ if (((ProtocolClass)pc1).getIncomingMessages().size()>0)
+ pc1extendsIncoming = true;
+ if (((ProtocolClass)pc1).getOutgoingMessages().size()>0)
+ pc1extendsOutgoing = true;
+ if (pc1extendsIncoming && pc1extendsOutgoing)
+ return Result.error("derived protocols not connectable (both directions extended)");
+
+ }
+ else if (RoomHelpers.isDerivedFrom((ProtocolClass)pc2, (ProtocolClass)pc1)) {
+ if (((ProtocolClass)pc2).getIncomingMessages().size()>0)
+ pc2extendsIncoming = true;
+ if (((ProtocolClass)pc2).getOutgoingMessages().size()>0)
+ pc2extendsOutgoing = true;
+ if (pc2extendsIncoming && pc2extendsOutgoing)
+ return Result.error("derived protocols not connectable (both directions extended)");
+ }
+ else
+ return Result.error("protocols don't match");
+ }
+ }
}
if (checkCompound || !compoundInvolved) {
@@ -360,6 +388,15 @@ public class ValidationUtil {
if (p1.isConjugated()==p2.isConjugated())
return Result.error("connected sub component ports must be conjugated to each other");
+ if (p1.isConjugated() && pc1extendsIncoming)
+ return Result.error("protocol extends incoming");
+ if (p2.isConjugated() && pc2extendsIncoming)
+ return Result.error("protocol extends incoming");
+ if (!p1.isConjugated() && pc1extendsOutgoing)
+ return Result.error("protocol extends outgoing");
+ if (!p2.isConjugated() && pc2extendsOutgoing)
+ return Result.error("protocol extends outgoing");
+
Result result = isConnectable(p1, ref1, sc, exclude);
if (!result.isOk())
return result;
@@ -378,6 +415,26 @@ public class ValidationUtil {
if (local.isConjugated()!=sub.isConjugated())
return Result.error("relay port must have same direction as local port");
+ if (local==p1) {
+ if (!p1.isConjugated() && pc1extendsIncoming)
+ return Result.error("protocol extends incoming");
+ if (p2.isConjugated() && pc2extendsIncoming)
+ return Result.error("protocol extends incoming");
+ if (p1.isConjugated() && pc1extendsOutgoing)
+ return Result.error("protocol extends outgoing");
+ if (!p2.isConjugated() && pc2extendsOutgoing)
+ return Result.error("protocol extends outgoing");
+ }
+ else {
+ if (p1.isConjugated() && pc1extendsIncoming)
+ return Result.error("protocol extends incoming");
+ if (!p2.isConjugated() && pc2extendsIncoming)
+ return Result.error("protocol extends incoming");
+ if (!p1.isConjugated() && pc1extendsOutgoing)
+ return Result.error("protocol extends outgoing");
+ if (p2.isConjugated() && pc2extendsOutgoing)
+ return Result.error("protocol extends outgoing");
+ }
Result result = isConnectable(local, null, acc, exclude);
if (!result.isOk())
return result;
@@ -390,6 +447,15 @@ public class ValidationUtil {
if (local.isConjugated()==sub.isConjugated())
return Result.error("internal end port must have opposite direction");
+
+ if (p1.isConjugated() && pc1extendsIncoming)
+ return Result.error("protocol extends incoming");
+ if (p2.isConjugated() && pc2extendsIncoming)
+ return Result.error("protocol extends incoming");
+ if (!p1.isConjugated() && pc1extendsOutgoing)
+ return Result.error("protocol extends outgoing");
+ if (!p2.isConjugated() && pc2extendsOutgoing)
+ return Result.error("protocol extends outgoing");
Result result = isConnectable(sub, ref, sc, exclude);
if (!result.isOk())
diff --git a/tests/org.eclipse.etrice.core.room.tests/models/TestBindings.room b/tests/org.eclipse.etrice.core.room.tests/models/TestBindings.room
new file mode 100644
index 000000000..47f081898
--- /dev/null
+++ b/tests/org.eclipse.etrice.core.room.tests/models/TestBindings.room
@@ -0,0 +1,104 @@
+RoomModel TestBindings {
+ LogicalSystem Sys {
+ SubSystemRef main: Application
+ }
+
+ SubSystemClass Application {
+ ActorRef ref1: AC1
+ ActorRef ref2: AC2
+
+ // no self connection allowed, ports are indentical
+ Binding ref1.reg and ref1.reg
+
+ // port with multiplicity 1 is already connected
+ Binding ref1.reg and ref2.conj
+ Binding ref1.reg and ref2.conj
+
+ // protocols don't match
+ Binding ref1.reg and ref2.other
+
+ // protocol extends incoming
+ Binding ref1.base and ref2.extin
+
+ // ok
+ Binding ref1.base2 and ref2.extout
+
+ // protocol extends outgoing
+ Binding ref1.base3 and ref2.extout2
+
+ // derived protocols not connectable (both directions extended)
+ Binding ref1.base4 and ref2.extinout
+
+ LogicalThread dflt_thread
+ }
+
+ ActorClass AC1 {
+ Interface {
+ Port reg: PC1
+ Port base: PCBase
+ Port base2: PCBase
+ conjugated Port base3: PCBase
+ conjugated Port base4: PCBase
+ }
+ Structure {
+ external Port reg
+ }
+ Behavior { }
+ }
+
+ ActorClass AC2 {
+ Interface {
+ conjugated Port conj: PC1
+ conjugated Port other: PC2
+ conjugated Port extout: PCExtendOut
+ conjugated Port extin: PCExtendIn
+ Port extout2: PCExtendOut
+ Port extinout: PCExtendInOut
+ }
+ Structure {
+ external Port conj
+ }
+ Behavior { }
+ }
+
+ ProtocolClass PC1 {
+ incoming {
+ Message in1()
+ }
+ }
+
+ ProtocolClass PC2 {
+ incoming {
+ Message in1()
+ }
+ }
+
+ ProtocolClass PCBase {
+ incoming {
+ Message in1()
+ }
+ }
+
+ ProtocolClass PCExtendIn extends PCBase {
+ incoming {
+ Message in2()
+ }
+ }
+
+ ProtocolClass PCExtendOut extends PCBase {
+ outgoing {
+ Message out1()
+ }
+ }
+
+ ProtocolClass PCExtendInOut extends PCBase {
+ incoming {
+ Message in2()
+ }
+ outgoing {
+ // a derived protocol should add either incoming or outgoing messages, not both
+ Message out1()
+ }
+ }
+
+} \ No newline at end of file
diff --git a/tests/org.eclipse.etrice.core.room.tests/src/org/eclipse/etrice/core/TestBindings.java b/tests/org.eclipse.etrice.core.room.tests/src/org/eclipse/etrice/core/TestBindings.java
new file mode 100644
index 000000000..d370d16b5
--- /dev/null
+++ b/tests/org.eclipse.etrice.core.room.tests/src/org/eclipse/etrice/core/TestBindings.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2012 protos software gmbh (http://www.protos.de).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * CONTRIBUTORS:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+
+package org.eclipse.etrice.core;
+
+import static org.junit.Assert.*;
+
+import org.eclipse.emf.common.util.Diagnostic;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.etrice.core.room.Binding;
+import org.eclipse.etrice.core.room.GeneralProtocolClass;
+import org.eclipse.etrice.core.room.RoomModel;
+import org.eclipse.etrice.core.room.SubSystemClass;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Henrik Rentz-Reichert
+ *
+ */
+public class TestBindings extends TestBase {
+ private Resource resource;
+
+ @Before
+ public void setUp() {
+ prepare();
+
+ resource = getResource("TestBindings.room");
+ }
+
+ @Test
+ public void testBindingValidation() {
+ RoomModel mdl = (RoomModel) resource.getContents().get(0);
+ SubSystemClass ssc = mdl.getSubSystemClasses().get(0);
+ Binding bind = ssc.getBindings().get(0);
+ Diagnostic diag = getDiag(bind).getChildren().get(0);
+ assertEquals("expect error message", "no self connection allowed, ports are indentical", diag.getMessage());
+
+ bind = ssc.getBindings().get(1);
+ diag = getDiag(bind).getChildren().get(0);
+ assertEquals("expect error message", "port with multiplicity 1 is already connected", diag.getMessage());
+
+ bind = ssc.getBindings().get(2);
+ diag = getDiag(bind).getChildren().get(0);
+ assertEquals("expect error message", "port with multiplicity 1 is already connected", diag.getMessage());
+
+ bind = ssc.getBindings().get(3);
+ diag = getDiag(bind).getChildren().get(0);
+ assertEquals("protocols don't match", diag.getMessage());
+
+ bind = ssc.getBindings().get(4);
+ diag = getDiag(bind).getChildren().get(0);
+ assertEquals("protocol extends incoming", diag.getMessage());
+
+ bind = ssc.getBindings().get(6);
+ diag = getDiag(bind).getChildren().get(0);
+ assertEquals("protocol extends outgoing", diag.getMessage());
+
+ bind = ssc.getBindings().get(7);
+ diag = getDiag(bind).getChildren().get(0);
+ assertEquals("derived protocols not connectable (both directions extended)", diag.getMessage());
+ }
+
+ @Test
+ public void testProtocolValidation() {
+ RoomModel mdl = (RoomModel) resource.getContents().get(0);
+ for (GeneralProtocolClass pc : mdl.getProtocolClasses()) {
+ if (pc.getName().equals("PCExtendInOut")) {
+ Diagnostic diag = getDiag(pc).getChildren().get(0);
+ assertEquals("a derived protocol should add either incoming or outgoing messages, not both", diag.getMessage());
+ }
+ }
+ }
+}

Back to the top