[New] Implemented StrolchTransaction.findElement(Locator)

Now using a locator, it is possible to query a StrolchElement. It is
possible to query top level i.e. Resource/Order or ParameterBag, or
Parameter.
This commit is contained in:
Robert von Burg 2014-01-13 19:10:14 +01:00
parent a446a25a2e
commit 4c71dcfa3f
5 changed files with 168 additions and 2 deletions

View File

@ -24,6 +24,7 @@ public abstract class TransactionalElementMap<T extends StrolchElement> implemen
@Override
public boolean hasElement(StrolchTransaction tx, String type, String id) {
// TODO change to dao.hasElement(type, id)
return getDao(tx).queryKeySet(type).contains(id);
}

View File

@ -15,9 +15,19 @@
*/
package li.strolch.persistence.api;
import java.text.MessageFormat;
import java.util.List;
import li.strolch.agent.api.OrderMap;
import li.strolch.agent.api.ResourceMap;
import li.strolch.agent.impl.StrolchRealm;
import li.strolch.exception.StrolchException;
import li.strolch.model.GroupedParameterizedElement;
import li.strolch.model.Locator;
import li.strolch.model.ParameterBag;
import li.strolch.model.StrolchElement;
import li.strolch.model.Tags;
import li.strolch.model.parameter.Parameter;
import li.strolch.persistence.inmemory.InMemoryTransaction;
import org.slf4j.Logger;
@ -54,4 +64,58 @@ public abstract class AbstractTransaction implements StrolchTransaction {
public OrderMap getOrderMap() {
return this.realm.getOrderMap();
}
@SuppressWarnings("unchecked")
@Override
public <T extends StrolchElement> T findElement(Locator locator) {
if (locator.getSize() < 3) {
String msg = "The locator is invalid as it does not have at least three path elements (e.g. Resource/MyType/@id): {0}";
msg = MessageFormat.format(msg, locator.toString());
throw new StrolchException(msg);
} else if (locator.getSize() > 5) {
// TODO handle state variables, which will probably be separated by an additional part so we can differentiate between parameters and state variables on a parameter bag
String msg = "The locator is invalid as it has more than 5 parts. The fifth part references a Parameter, which is the deepest fetchable entry: {0}";
msg = MessageFormat.format(msg, locator.toString());
throw new StrolchException(msg);
}
List<String> elements = locator.getPathElements();
GroupedParameterizedElement groupedParameterizedElement;
String objectClassType = elements.get(0);
String type = elements.get(1);
String id = elements.get(2);
switch (objectClassType) {
case Tags.RESOURCE:
groupedParameterizedElement = getResourceMap().getBy(this, type, id);
break;
case Tags.ORDER:
groupedParameterizedElement = getOrderMap().getBy(this, type, id);
break;
default:
throw new StrolchException("Unknown object class " + objectClassType);
}
if (groupedParameterizedElement == null) {
String msg = "No top level object could be found with locator {0}";
throw new StrolchException(MessageFormat.format(msg, locator));
}
if (elements.size() == 3)
return (T) groupedParameterizedElement;
String parameterBagId = elements.get(3);
ParameterBag bag = groupedParameterizedElement.getParameterBag(parameterBagId);
if (bag == null) {
String msg = "Could not find ParameterBag for locator {0} on element {1}";
throw new StrolchException(MessageFormat.format(msg, locator, groupedParameterizedElement.getLocator()));
}
if (elements.size() == 4)
return (T) bag;
String parameterId = elements.get(4);
Parameter<?> parameter = bag.getParameter(parameterId);
return (T) parameter;
}
}

View File

@ -28,6 +28,8 @@ public interface StrolchDao<T extends StrolchElement> {
public Set<String> queryKeySet();
// TODO add method hasElement(String type, String id)
public Set<String> queryKeySet(String type);
public Set<String> queryTypes();
@ -47,6 +49,6 @@ public interface StrolchDao<T extends StrolchElement> {
public void updateAll(List<T> elements);
public void remove(T element);
public void removeAll(List<T> elements);
}

View File

@ -17,6 +17,13 @@ package li.strolch.persistence.api;
import li.strolch.agent.api.OrderMap;
import li.strolch.agent.api.ResourceMap;
import li.strolch.exception.StrolchException;
import li.strolch.model.Locator;
import li.strolch.model.Order;
import li.strolch.model.ParameterBag;
import li.strolch.model.Resource;
import li.strolch.model.StrolchElement;
import li.strolch.model.parameter.Parameter;
public interface StrolchTransaction extends AutoCloseable {
@ -34,6 +41,35 @@ public interface StrolchTransaction extends AutoCloseable {
public ResourceMap getResourceMap();
public OrderMap getOrderMap();
public PersistenceHandler getPersistenceHandler();
/**
* <p>
* Used to find a {@link StrolchElement} by a {@link Locator}.
* </p>
*
* <p>
* A Locator has the form <i>&lt;ObjectClassType&gt;/&lt;Type&gt;/&lt;Id&gt;</i> - this is the least amount of path
* elements to find an object. Thus to query a {@link Resource} of type "MyType" and the id "@1" use the following
* path: <i>Resourcee/MyType/@1</i>
* </p>
*
* <p>
* This method can also be used to find a deeper element, e.g. a specific {@link Parameter} on an
* {@link ParameterBag} on an {@link Order}. This would be done as follows: <i>Order/MyType/@1/myParam</i>
* </p>
*
* @param locator
* the locator defining the path to the element which is to be found
*
* @return the element described by the locator
*
* @throws StrolchException
* if the element could not be found
* @throws ClassCastException
* if the querying code is not asking for the correct instance. Do not query a {@link Parameter} if the
* variable to which the result is to be is stored is a {@link Resource}, etc.
*/
public <T extends StrolchElement> T findElement(Locator locator) throws StrolchException, ClassCastException;
}

View File

@ -0,0 +1,63 @@
/*
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package li.strolch.runtime.test.query.inmemory;
import static org.junit.Assert.assertNotNull;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.agent.api.StrolchAgent;
import li.strolch.model.Locator;
import li.strolch.model.ParameterBag;
import li.strolch.model.Resource;
import li.strolch.model.parameter.FloatParameter;
import li.strolch.model.parameter.StringParameter;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.runtime.test.component.ComponentContainerTest;
import org.junit.Test;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class FindByLocatorTest {
private static final String PATH_FIND_BY_LOCATOR_RUNTIME = "target/FindByLocatorTest/";
@Test
public void shouldFindByLocator() {
StrolchAgent agent = ComponentContainerTest.startContainer(PATH_FIND_BY_LOCATOR_RUNTIME,
ComponentContainerTest.PATH_TRANSIENT_CONTAINER);
ComponentContainer container = agent.getContainer();
try (StrolchTransaction tx = container.getDefaultRealm().openTx()) {
Locator locResStringParam = Locator.valueOf("Resource/TestType/MyTestResource/@bag01/@param5");
StringParameter resStringParam = tx.findElement(locResStringParam);
assertNotNull("Should have found a StringParameter with the locator " + locResStringParam, resStringParam);
Locator locOrderFloatParam = Locator.valueOf("Order/TestType/MyTestOrder/@bag01/@param2");
FloatParameter orderFloatP = tx.findElement(locOrderFloatParam);
assertNotNull("Should have found a FloatParameter with the locator " + locOrderFloatParam, orderFloatP);
Locator locOrderBag = Locator.valueOf("Order/TestType/MyTestOrder/@bag01");
ParameterBag orderBag = tx.findElement(locOrderBag);
assertNotNull("Should have found a FloatParameter with the locator " + locOrderBag, orderBag);
Locator locResource = Locator.valueOf("Resource/TestType/MyTestResource");
Resource resource = tx.findElement(locResource);
assertNotNull("Should have found a FloatParameter with the locator " + locResource, resource);
}
}
}