diff --git a/FROST-Server.Core/src/main/java/de/fraunhofer/iosb/ilt/frostserver/mqtt/subscription/AbstractSubscription.java b/FROST-Server.Core/src/main/java/de/fraunhofer/iosb/ilt/frostserver/mqtt/subscription/AbstractSubscription.java index b2e80cf1b..cee0e0d97 100644 --- a/FROST-Server.Core/src/main/java/de/fraunhofer/iosb/ilt/frostserver/mqtt/subscription/AbstractSubscription.java +++ b/FROST-Server.Core/src/main/java/de/fraunhofer/iosb/ilt/frostserver/mqtt/subscription/AbstractSubscription.java @@ -26,6 +26,7 @@ import de.fraunhofer.iosb.ilt.frostserver.path.PathElement; import de.fraunhofer.iosb.ilt.frostserver.path.PathElementEntity; import de.fraunhofer.iosb.ilt.frostserver.path.PathElementEntitySet; +import de.fraunhofer.iosb.ilt.frostserver.path.PathElementEntityType; import de.fraunhofer.iosb.ilt.frostserver.path.ResourcePath; import de.fraunhofer.iosb.ilt.frostserver.persistence.PersistenceManager; import de.fraunhofer.iosb.ilt.frostserver.property.NavigationPropertyMain; @@ -94,21 +95,32 @@ public boolean matches(PersistenceManager persistenceManager, Entity newEntity, } protected void generateFilter(int pathElementOffset) { - EntityType lastType = getEntityType(); - List properties = new ArrayList<>(); + final List properties = new ArrayList<>(); boolean direct = true; - for (int i = path.size() - 1 - pathElementOffset; i >= 0; i--) { + final int size = path.size(); + final int startIdx = size - 1 - pathElementOffset; + if (startIdx < 0) { + return; + } + PathElement nextPathElement = startIdx < size ? path.get(startIdx + 1) : null; + for (int i = startIdx; i >= 0; i--) { PathElement element = path.get(i); - if (element instanceof PathElementEntitySet) { - final PathElementEntitySet pees = (PathElementEntitySet) element; - final NavigationPropertyMain navProp = lastType.getNavigationProperty(pees.getEntityType()); - properties.add(navProp); - lastType = pees.getEntityType(); + if (element instanceof PathElementEntitySet pees) { + NavigationPropertyMain navPropInverse = null; + if (nextPathElement instanceof PathElementEntityType peet) { + final NavigationPropertyMain navProp = peet.getNavigationProperty(); + if (navProp != null) { + navPropInverse = navProp.getInverse(); + } + } + properties.add(navPropInverse); direct = false; - } else if (element instanceof PathElementEntity) { - final PathElementEntity epe = (PathElementEntity) element; - final NavigationPropertyMain navProp = lastType.getNavigationProperty(epe.getEntityType()); + } else if (element instanceof PathElementEntity epe) { + NavigationPropertyMain navProp = null; + if (nextPathElement instanceof PathElementEntityType peet) { + navProp = peet.getNavigationProperty().getInverse(); + } final Id id = epe.getId(); if (direct && navProp != null && !navProp.isEntitySet() && id != null) { @@ -118,7 +130,6 @@ protected void generateFilter(int pathElementOffset) { } properties.add(navProp); - lastType = epe.getEntityType(); if (id != null) { createMatchExpression(properties, epe); @@ -127,6 +138,7 @@ protected void generateFilter(int pathElementOffset) { return; } } + nextPathElement = element; } } diff --git a/FROST-Server.Core/src/test/java/de/fraunhofer/iosb/ilt/frostserver/mqtt/MqttManagerTest.java b/FROST-Server.Core/src/test/java/de/fraunhofer/iosb/ilt/frostserver/mqtt/MqttManagerTest.java index b95719906..6b4116396 100644 --- a/FROST-Server.Core/src/test/java/de/fraunhofer/iosb/ilt/frostserver/mqtt/MqttManagerTest.java +++ b/FROST-Server.Core/src/test/java/de/fraunhofer/iosb/ilt/frostserver/mqtt/MqttManagerTest.java @@ -71,7 +71,7 @@ class MqttManagerTest { private static final Logger LOGGER = LoggerFactory.getLogger(MqttManagerTest.class.getName()); private static final int REPEAT_COUNT = 0; - private static final int MESSAGE_COUNT = 20000; + private static final int MESSAGE_COUNT = 2000; private CoreSettings coreSettings; private ModelRegistry modelRegistry; @@ -79,6 +79,7 @@ class MqttManagerTest { @BeforeEach public void init() { + TestMqttServerRegister.getInstance().clear(); Properties properties = new Properties(); properties.put(CoreSettings.TAG_SERVICE_ROOT_URL, "http://localhost/"); properties.put(CoreSettings.TAG_TEMP_PATH, System.getProperty("java.io.tmpdir")); @@ -109,6 +110,17 @@ void testVersionParseFail() { }); } + @Test + void testSubscriptions() throws InterruptedException { + MqttManager mqttManager = new MqttManager(coreSettings); + List mqttServers = TestMqttServerRegister.getInstance().getServers(); + TestMqttServer mqttServer = mqttServers.get(0); + mqttServer.subscribe("v1.1/Houses"); + mqttServer.subscribe("v1.1/Houses(1)"); + mqttServer.subscribe("v1.1/Houses(1)/Rooms"); + mqttServer.subscribe("v1.1/Rooms(1)/House"); + } + @Test void testMqttManager() throws InterruptedException { MqttManager mqttManager = new MqttManager(coreSettings); @@ -161,7 +173,7 @@ private void testTopics(List mqttServers, MqttManager mqttManage .setEntity( new DefaultEntity(testModel.ET_ROOM, new IdLong(pubId)) .setProperty(testModel.EP_NAME, "" + pubId) - .setProperty(testModel.NP_HOUSE, new DefaultEntity(testModel.ET_HOUSE, new IdLong(topicId)))); + .setProperty(testModel.NP_ROOM_HOUSE, new DefaultEntity(testModel.ET_HOUSE, new IdLong(topicId)))); topicId++; if (topicId >= subscriptionCount) { topicId = 0; @@ -194,8 +206,8 @@ private void add(TestMqttServer server) { servers.add(server); } - private boolean remove(TestMqttServer server) { - return servers.remove(server); + private void clear() { + servers.clear(); } public List getServers() { diff --git a/FROST-Server.Core/src/test/java/de/fraunhofer/iosb/ilt/frostserver/query/QueryParserTest.java b/FROST-Server.Core/src/test/java/de/fraunhofer/iosb/ilt/frostserver/query/QueryParserTest.java index fe81d5d68..e6a515bab 100644 --- a/FROST-Server.Core/src/test/java/de/fraunhofer/iosb/ilt/frostserver/query/QueryParserTest.java +++ b/FROST-Server.Core/src/test/java/de/fraunhofer/iosb/ilt/frostserver/query/QueryParserTest.java @@ -175,7 +175,7 @@ void testFilterLinked() { String query = "$filter=House/id eq 1"; Query expResult = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); expResult.setFilter(new Equal( - new Path(testModel.NP_HOUSE, testModel.ET_HOUSE.getPrimaryKey()), + new Path(testModel.NP_ROOM_HOUSE, testModel.ET_HOUSE.getPrimaryKey()), new IntegerConstant(1))); Query result = QueryParser.parseQuery(query, coreSettings, path); result.validate(testModel.ET_ROOM); @@ -185,7 +185,7 @@ void testFilterLinked() { query = "$filter=House/Rooms/name eq 1"; expResult = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); expResult.setFilter(new Equal( - new Path(testModel.NP_HOUSE, testModel.NP_ROOMS, testModel.EP_NAME), + new Path(testModel.NP_ROOM_HOUSE, testModel.NP_HOUSE_ROOMS, testModel.EP_NAME), new IntegerConstant(1))); result = QueryParser.parseQuery(query, coreSettings, path); result.validate(testModel.ET_ROOM); @@ -541,7 +541,7 @@ void testOrderByAliasAscDesc() { void testOrderByMixedPath() { String query = "$orderby=House/@iot.id"; Query expResult = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); - expResult.getOrderBy().add(new OrderBy(new Path(testModel.NP_HOUSE, testModel.ET_HOUSE.getPrimaryKey()))); + expResult.getOrderBy().add(new OrderBy(new Path(testModel.NP_ROOM_HOUSE, testModel.ET_HOUSE.getPrimaryKey()))); Query result = QueryParser.parseQuery(query, coreSettings, path); result.validate(testModel.ET_ROOM); assertEquals(expResult, result); @@ -562,18 +562,18 @@ void testOrderByMixedPath() { @Test void testSelect() { Query expResult = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); - expResult.getSelect().add(testModel.NP_ROOMS); + expResult.getSelect().add(testModel.NP_HOUSE_ROOMS); expResult.getSelect().add(testModel.ET_HOUSE.getPrimaryKey()); Query result = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); - result.addSelect(testModel.NP_ROOMS) + result.addSelect(testModel.NP_HOUSE_ROOMS) .addSelect(testModel.ET_HOUSE.getPrimaryKey()); assertEquals(expResult, result); expResult.getSelect().clear(); - expResult.getSelect().add(testModel.NP_HOUSE); + expResult.getSelect().add(testModel.NP_ROOM_HOUSE); expResult.getSelect().add(testModel.ET_ROOM.getPrimaryKey()); result.clearSelect(); - result.addSelect(testModel.NP_HOUSE) + result.addSelect(testModel.NP_ROOM_HOUSE) .addSelect(testModel.ET_ROOM.getPrimaryKey()); assertEquals(expResult, result); } @@ -676,7 +676,7 @@ void testSelectDistinct() { void testSelectNavigationProperty() { String query = "$select=Rooms"; Query expResult = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); - expResult.getSelect().add(testModel.NP_ROOMS); + expResult.getSelect().add(testModel.NP_HOUSE_ROOMS); Query result = QueryParser.parseQuery(query, coreSettings, path); result.validate(testModel.ET_HOUSE); assertEquals(expResult, result); @@ -686,7 +686,7 @@ void testSelectNavigationProperty() { void testSelectMultipleMixed() { String query = "$select=Rooms, id"; Query expResult = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); - expResult.addSelect(testModel.NP_ROOMS) + expResult.addSelect(testModel.NP_HOUSE_ROOMS) .addSelect(testModel.ET_HOUSE.getPrimaryKey()); Query result = QueryParser.parseQuery(query, coreSettings, path); result.validate(testModel.ET_HOUSE); @@ -697,7 +697,7 @@ void testSelectMultipleMixed() { void testExpandSingleNavigationProperty() { String query = "$expand=Rooms"; Query expResult = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); - expResult.getExpand().add(new Expand(modelRegistry, testModel.NP_ROOMS)); + expResult.getExpand().add(new Expand(modelRegistry, testModel.NP_HOUSE_ROOMS)); Query result = QueryParser.parseQuery(query, coreSettings, path); result.validate(testModel.ET_HOUSE); assertEquals(expResult, result); @@ -707,7 +707,7 @@ void testExpandSingleNavigationProperty() { void testExpandSingleNavigationPropertyEmpty() { String query = "$expand=Rooms()"; Query expResult = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); - expResult.getExpand().add(new Expand(modelRegistry, testModel.NP_ROOMS)); + expResult.getExpand().add(new Expand(modelRegistry, testModel.NP_HOUSE_ROOMS)); Query result = QueryParser.parseQuery(query, coreSettings, path); result.validate(testModel.ET_HOUSE); assertEquals(expResult, result); @@ -717,9 +717,9 @@ void testExpandSingleNavigationPropertyEmpty() { void testExpandDeep() { String query = "$expand=Rooms/House"; Query subQuery = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); - subQuery.getExpand().add(new Expand(modelRegistry, testModel.NP_HOUSE)); + subQuery.getExpand().add(new Expand(modelRegistry, testModel.NP_ROOM_HOUSE)); Query expResult = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); - expResult.getExpand().add(new Expand(modelRegistry, subQuery, testModel.NP_ROOMS)); + expResult.getExpand().add(new Expand(modelRegistry, subQuery, testModel.NP_HOUSE_ROOMS)); Query result = QueryParser.parseQuery(query, coreSettings, path); result.validate(testModel.ET_HOUSE); assertEquals(expResult, result); @@ -785,9 +785,9 @@ void testExpandDeepQuery() { Query subQuery = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); Query subSubQuery = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); subSubQuery.getSelect().add(testModel.ET_HOUSE.getPrimaryKey()); - subQuery.getExpand().add(new Expand(modelRegistry, subSubQuery, testModel.NP_HOUSE)); + subQuery.getExpand().add(new Expand(modelRegistry, subSubQuery, testModel.NP_ROOM_HOUSE)); Query expResult = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); - expResult.getExpand().add(new Expand(modelRegistry, subQuery, testModel.NP_ROOMS)); + expResult.getExpand().add(new Expand(modelRegistry, subQuery, testModel.NP_HOUSE_ROOMS)); Query result = QueryParser.parseQuery(query, coreSettings, path); result.validate(testModel.ET_HOUSE); assertEquals(expResult, result); @@ -797,8 +797,8 @@ void testExpandDeepQuery() { void testExpandMultipleNavigationProperties() { String query = "$expand=Rooms,House"; Query expResult = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); - expResult.getExpand().add(new Expand(modelRegistry, testModel.NP_ROOMS)); - expResult.getExpand().add(new Expand(modelRegistry, testModel.NP_HOUSE)); + expResult.getExpand().add(new Expand(modelRegistry, testModel.NP_HOUSE_ROOMS)); + expResult.getExpand().add(new Expand(modelRegistry, testModel.NP_ROOM_HOUSE)); Query result = QueryParser.parseQuery(query, coreSettings, path); assertEquals(expResult, result); } @@ -807,10 +807,10 @@ void testExpandMultipleNavigationProperties() { void testExpandMultipleNavigationPropertiesDeep1() { String query = "$expand=Rooms/House,Rooms/Rooms"; Query expResult = new Query(modelRegistry, coreSettings.getQueryDefaults(), path) - .addExpand(new Expand(modelRegistry, testModel.NP_ROOMS) + .addExpand(new Expand(modelRegistry, testModel.NP_HOUSE_ROOMS) .setSubQuery(new Query(modelRegistry, coreSettings.getQueryDefaults(), path) - .addExpand(new Expand(modelRegistry, testModel.NP_HOUSE)) - .addExpand(new Expand(modelRegistry, testModel.NP_ROOMS)))); + .addExpand(new Expand(modelRegistry, testModel.NP_ROOM_HOUSE)) + .addExpand(new Expand(modelRegistry, testModel.NP_HOUSE_ROOMS)))); Query result = QueryParser.parseQuery(query, coreSettings, path); result.validate(testModel.ET_HOUSE); assertEquals(expResult, result); @@ -822,8 +822,8 @@ void testExpandMultipleNavigationPropertiesDeep2() { Query expResult = new Query(modelRegistry, coreSettings.getQueryDefaults(), path) .addExpand(new Expand(modelRegistry, testModel.NP_HOUSES) .setSubQuery(new Query(modelRegistry, coreSettings.getQueryDefaults(), path) - .addExpand(new Expand(modelRegistry, testModel.NP_ROOMS)) - .addExpand(new Expand(modelRegistry, testModel.NP_HOUSE)))); + .addExpand(new Expand(modelRegistry, testModel.NP_HOUSE_ROOMS)) + .addExpand(new Expand(modelRegistry, testModel.NP_ROOM_HOUSE)))); Query result = QueryParser.parseQuery(query, coreSettings, path); assertEquals(expResult, result); } @@ -834,14 +834,14 @@ void testExpandWithSubquery() { Query expResult = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); Query subQuery = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); subQuery.setFilter(new Equal(new Path(testModel.EP_VALUE), new IntegerConstant(1))); - subQuery.getExpand().add(new Expand(modelRegistry, testModel.NP_HOUSE)); + subQuery.getExpand().add(new Expand(modelRegistry, testModel.NP_ROOM_HOUSE)); subQuery.getSelect().add(testModel.ET_ROOM.getPrimaryKey()); subQuery.getOrderBy().add(new OrderBy(new Path(testModel.ET_ROOM.getPrimaryKey()))); subQuery.setSkip(5); subQuery.setTop(10); subQuery.setCount(true); - expResult.getExpand().add(new Expand(modelRegistry, subQuery, testModel.NP_ROOMS)); - expResult.getExpand().add(new Expand(modelRegistry, testModel.NP_HOUSE)); + expResult.getExpand().add(new Expand(modelRegistry, subQuery, testModel.NP_HOUSE_ROOMS)); + expResult.getExpand().add(new Expand(modelRegistry, testModel.NP_ROOM_HOUSE)); expResult.setTop(10); Query result = QueryParser.parseQuery(query, coreSettings, path); result.validate(testModel.ET_ROOM); @@ -854,10 +854,10 @@ void testComplex1() { Query expResult = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); Query subQuery1 = new Query(modelRegistry, coreSettings.getQueryDefaults(), path); subQuery1.setFilter(new Equal(new Path(testModel.EP_VALUE), new IntegerConstant(1))); - subQuery1.getExpand().add(new Expand(modelRegistry, testModel.NP_HOUSE)); + subQuery1.getExpand().add(new Expand(modelRegistry, testModel.NP_ROOM_HOUSE)); subQuery1.getSelect().add(testModel.ET_ROOM.getPrimaryKey()); - expResult.getExpand().add(new Expand(modelRegistry, subQuery1, testModel.NP_ROOMS)); - expResult.getExpand().add(new Expand(modelRegistry, testModel.NP_HOUSE)); + expResult.getExpand().add(new Expand(modelRegistry, subQuery1, testModel.NP_HOUSE_ROOMS)); + expResult.getExpand().add(new Expand(modelRegistry, testModel.NP_ROOM_HOUSE)); expResult.setTop(10); Query result = QueryParser.parseQuery(query, coreSettings, path); result.validate(testModel.ET_ROOM); @@ -873,18 +873,18 @@ void testFilterComplex() { new And( new Equal( new Path( - testModel.NP_ROOMS, - testModel.NP_HOUSE, + testModel.NP_HOUSE_ROOMS, + testModel.NP_ROOM_HOUSE, testModel.ET_HOUSE.getPrimaryKey()), new StringConstant("FOI_1")), new GreaterEqual( - new Path(testModel.NP_HOUSE, - testModel.NP_ROOMS, + new Path(testModel.NP_ROOM_HOUSE, + testModel.NP_HOUSE_ROOMS, testModel.EP_TIME), new DateTimeConstant(PlainTimestamp.of(2010, 06, 01, 0, 0).inZonalView(TIMEZONE_UTC)))), new LessEqual( - new Path(testModel.NP_HOUSE, - testModel.NP_ROOMS, + new Path(testModel.NP_ROOM_HOUSE, + testModel.NP_HOUSE_ROOMS, testModel.EP_TIME), new DateTimeConstant(PlainTimestamp.of(2010, 07, 01, 0, 0).inZonalView(TIMEZONE_UTC))))); Query result = QueryParser.parseQuery(query, coreSettings, path); diff --git a/FROST-Server.Core/src/test/java/de/fraunhofer/iosb/ilt/frostserver/util/TestModel.java b/FROST-Server.Core/src/test/java/de/fraunhofer/iosb/ilt/frostserver/util/TestModel.java index 7a630a074..685bc3eff 100644 --- a/FROST-Server.Core/src/test/java/de/fraunhofer/iosb/ilt/frostserver/util/TestModel.java +++ b/FROST-Server.Core/src/test/java/de/fraunhofer/iosb/ilt/frostserver/util/TestModel.java @@ -54,10 +54,10 @@ public class TestModel implements PluginService { public final EntityPropertyMain EP_VALUE = new EntityPropertyMain<>("value", TypeSimplePrimitive.EDM_DECIMAL); public final EntityPropertyMain EP_TIME = new EntityPropertyMain<>("time", TypeSimplePrimitive.EDM_DATETIMEOFFSET); - public final NavigationPropertyEntity NP_HOUSE = new NavigationPropertyEntity("House", true); - public final NavigationPropertyEntitySet NP_HOUSES = new NavigationPropertyEntitySet("Houses"); + public final NavigationPropertyEntity NP_ROOM_HOUSE = new NavigationPropertyEntity("House", true); + public final NavigationPropertyEntitySet NP_HOUSE_ROOMS = new NavigationPropertyEntitySet("Rooms", NP_ROOM_HOUSE); - public final NavigationPropertyEntitySet NP_ROOMS = new NavigationPropertyEntitySet("Rooms"); + public final NavigationPropertyEntitySet NP_HOUSES = new NavigationPropertyEntitySet("Houses"); public final EntityType ET_HOUSE = new EntityType("House", "Houses"); public final EntityType ET_ROOM = new EntityType("Room", "Rooms"); @@ -68,15 +68,15 @@ public void initModel(ModelRegistry modelRegistry, String idType) { .registerProperty(EP_NAME) .registerProperty(EP_VALUE) .registerProperty(ModelRegistry.EP_PROPERTIES) - .registerProperty(NP_ROOMS); + .registerProperty(NP_HOUSE_ROOMS); modelRegistry.registerEntityType(ET_ROOM); ET_ROOM.registerProperty(new EntityPropertyMain<>(AT_IOT_ID, modelRegistry.getPropertyType(idType)).setAliases("id")) .registerProperty(EP_NAME) .registerProperty(EP_VALUE) .registerProperty(EP_TIME) .registerProperty(ModelRegistry.EP_PROPERTIES) - .registerProperty(NP_ROOMS) - .registerProperty(NP_HOUSE); + .registerProperty(NP_HOUSE_ROOMS) + .registerProperty(NP_ROOM_HOUSE); } public Entity createHouse(int id, String name, double value) { @@ -120,17 +120,17 @@ public Map> getTestPropertyValues(ModelRegistr propertyValuesRoom.put(ModelRegistry.EP_SELFLINK, "http://my.self/link"); int nextId = 100; - propertyValuesRoom.put(NP_HOUSE, new DefaultEntity(ET_HOUSE, new IdLong(nextId++))); + propertyValuesRoom.put(NP_ROOM_HOUSE, new DefaultEntity(ET_HOUSE, new IdLong(nextId++))); EntitySetImpl rooms = new EntitySetImpl(ET_ROOM); rooms.add(new DefaultEntity(ET_ROOM, new IdLong(nextId++))); rooms.add(new DefaultEntity(ET_ROOM, new IdLong(nextId++))); - propertyValuesHouse.put(NP_ROOMS, rooms); + propertyValuesHouse.put(NP_HOUSE_ROOMS, rooms); EntitySetImpl houses = new EntitySetImpl(ET_HOUSE); houses.add(new DefaultEntity(ET_HOUSE, new IdLong(nextId++))); houses.add(new DefaultEntity(ET_HOUSE, new IdLong(nextId++))); - propertyValuesRoom.put(NP_ROOMS, houses); + propertyValuesRoom.put(NP_HOUSE_ROOMS, houses); return propertyValues; } diff --git a/FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/tables/StaTableAbstract.java b/FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/tables/StaTableAbstract.java index 69d72d00d..5942320fd 100644 --- a/FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/tables/StaTableAbstract.java +++ b/FROST-Server.SQLjooq/src/main/java/de/fraunhofer/iosb/ilt/frostserver/persistence/pgjooq/tables/StaTableAbstract.java @@ -214,7 +214,7 @@ public void setSecurityWrapper(SecurityTableWrapper securityWrapper) { public Relation findRelation(String name) { Relation relation = relations.get(name); if (relation == null) { - throw new IllegalStateException(DO_NOT_KNOW_HOW_TO_JOIN + name + " on " + getName() + " " + getClass().getName()); + throw new IllegalStateException(DO_NOT_KNOW_HOW_TO_JOIN + name + " on " + getName() + " " + getEntityType() + " " + getClass().getName()); } return relation; }