[Major] Implemented opt-in versioning

- adding versioning tests
- fixing broken tests
- implemented missing PostgreSQL DAO methods
This commit is contained in:
Robert von Burg 2016-08-07 11:49:36 +02:00
parent 880bb27abc
commit 26961b33cc
27 changed files with 974 additions and 138 deletions

View File

@ -278,7 +278,7 @@ public abstract class CachedElementMap<T extends StrolchRootElement> implements
if (this.realm.isVersioningEnabled()) {
// first perform cached change
getCachedDao().update(element);
getCachedDao().remove(element);
// last is to perform DB changes
getDbDao(tx).update(element);
@ -303,7 +303,7 @@ public abstract class CachedElementMap<T extends StrolchRootElement> implements
if (this.realm.isVersioningEnabled()) {
// first perform cached change
getCachedDao().updateAll(elements);
getCachedDao().removeAll(elements);
// last is to perform DB changes
getDbDao(tx).updateAll(elements);
@ -397,7 +397,7 @@ public abstract class CachedElementMap<T extends StrolchRootElement> implements
getCachedDao().remove(element);
getDbDao(tx).remove(element);
} else {
T previous = getBy(tx, type, id, elementVersion.getPreviousVersion(), false);
T previous = getBy(tx, type, id, elementVersion.getPreviousVersion(), true);
getCachedDao().update(previous);
getDbDao(tx).removeVersion(current);
}

View File

@ -130,6 +130,18 @@ public interface StrolchDao<T extends StrolchRootElement> {
*/
public List<T> queryVersionsFor(String type, String id);
/**
* Queries and returns the number of versions for the element with the given type and ID
*
* @param type
* the type of the element to be queried
* @param id
* the id of the element to be queried
*
* @return the number of versions for the element with the given type and ID
*/
public long queryVersionsSizeFor(String type, String id);
/**
* Queries and returns all elements regardless of type
*

View File

@ -23,6 +23,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import li.strolch.model.StrolchRootElement;
import li.strolch.persistence.api.StrolchDao;
@ -53,12 +55,11 @@ public class InMemoryDao<T extends StrolchRootElement> implements StrolchDao<T>
@Override
public synchronized long querySize() {
long size = 0;
for (String type : this.elementMap.keySet()) {
Map<String, ArrayDeque<T>> byType = this.elementMap.get(type);
size += byType.size();
}
return size;
return this.elementMap.entrySet().stream().map(e -> {
return e.getValue().entrySet().stream().filter(f -> {
return !f.getValue().getLast().getVersion().isDeleted();
}).count();
}).mapToInt(e -> e.intValue()).sum();
}
@Override
@ -66,19 +67,19 @@ public class InMemoryDao<T extends StrolchRootElement> implements StrolchDao<T>
Map<String, ArrayDeque<T>> byType = this.elementMap.get(type);
if (byType == null)
return 0;
return byType.size();
return byType.entrySet().stream().filter(e -> !e.getValue().getLast().getVersion().isDeleted()).count();
}
@Override
public synchronized Set<String> queryKeySet() {
Set<String> keySet = new HashSet<>();
for (String type : this.elementMap.keySet()) {
Map<String, ArrayDeque<T>> byType = this.elementMap.get(type);
for (String id : byType.keySet()) {
keySet.add(id);
}
}
return keySet;
return this.elementMap.entrySet().stream() //
.map(e -> {
return e.getValue().entrySet().stream() //
.filter(f -> !f.getValue().getLast().getVersion().isDeleted()) //
.map(f -> f.getKey());
}) //
.flatMap(Function.identity()) //
.collect(Collectors.toSet());
}
@Override
@ -86,7 +87,11 @@ public class InMemoryDao<T extends StrolchRootElement> implements StrolchDao<T>
Map<String, ArrayDeque<T>> byType = this.elementMap.get(type);
if (byType == null)
return new HashSet<>(0);
return new HashSet<>(byType.keySet());
return byType.entrySet().stream() //
.filter(e -> !e.getValue().getLast().getVersion().isDeleted()) //
.map(e -> e.getKey()) //
.collect(Collectors.toSet());
}
@Override
@ -139,19 +144,26 @@ public class InMemoryDao<T extends StrolchRootElement> implements StrolchDao<T>
}
@Override
public synchronized List<T> queryAll() {
List<T> elements = new ArrayList<>();
for (String type : this.elementMap.keySet()) {
Map<String, ArrayDeque<T>> byType = this.elementMap.get(type);
for (String id : byType.keySet()) {
ArrayDeque<T> list = byType.get(id);
T last = list.getLast();
if (last.getVersion() == null || !last.getVersion().isDeleted())
elements.add(last);
}
}
public long queryVersionsSizeFor(String type, String id) {
Map<String, ArrayDeque<T>> byType = this.elementMap.get(type);
if (byType == null)
return 0L;
ArrayDeque<T> list = byType.get(id);
if (list == null)
return 0L;
return list.size();
}
return elements;
@Override
public synchronized List<T> queryAll() {
return this.elementMap.entrySet().stream() //
.map(e -> {
return e.getValue().entrySet().stream() //
.filter(f -> !f.getValue().getLast().getVersion().isDeleted()) //
.map(f -> f.getValue().getLast());
}) //
.flatMap(Function.identity()) //
.collect(Collectors.toList());
}
@Override
@ -160,14 +172,10 @@ public class InMemoryDao<T extends StrolchRootElement> implements StrolchDao<T>
if (byType == null)
return new ArrayList<>(0);
List<T> elements = new ArrayList<>();
for (ArrayDeque<T> list : byType.values()) {
T last = list.getLast();
if (last.getVersion() == null || !last.getVersion().isDeleted())
elements.add(last);
}
return elements;
return byType.entrySet().stream() //
.filter(e -> !e.getValue().getLast().getVersion().isDeleted()) //
.map(e -> e.getValue().getLast()) //
.collect(Collectors.toList());
}
@Override

View File

@ -0,0 +1,303 @@
package li.strolch.runtime.query.inmemory;
import static li.strolch.model.query.ParameterSelection.booleanSelection;
import static li.strolch.model.query.ParameterSelection.floatListSelection;
import static li.strolch.model.query.ParameterSelection.floatSelection;
import static li.strolch.model.query.ParameterSelection.integerListSelection;
import static li.strolch.model.query.ParameterSelection.longListSelection;
import static li.strolch.model.query.ParameterSelection.stringListSelection;
import static li.strolch.model.query.ParameterSelection.stringSelection;
import static li.strolch.utils.StringMatchMode.ci;
import static li.strolch.utils.StringMatchMode.es;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import li.strolch.model.ModelGenerator;
import li.strolch.model.ParameterBag;
import li.strolch.model.Version;
import li.strolch.model.activity.Activity;
import li.strolch.model.parameter.BooleanParameter;
import li.strolch.model.parameter.FloatListParameter;
import li.strolch.model.parameter.FloatParameter;
import li.strolch.model.parameter.IntegerListParameter;
import li.strolch.model.parameter.LongListParameter;
import li.strolch.model.parameter.StringListParameter;
import li.strolch.model.parameter.StringParameter;
import li.strolch.model.query.ActivityQuery;
import li.strolch.model.query.IdSelection;
import li.strolch.model.query.NameSelection;
import li.strolch.model.query.ParameterSelection;
import li.strolch.persistence.inmemory.InMemoryActivityDao;
public class InMemoryActivityQueryTest {
protected InMemoryActivityDao daoInstance() {
return new InMemoryActivityDao(false);
}
@Test
public void shouldQueryById() {
List<Activity> activitys = getActivities();
InMemoryActivityDao dao = daoInstance();
dao.saveAll(activitys);
ActivityQuery<Activity> activityQuery = ActivityQuery.query("MyType1");
activityQuery.with(new IdSelection("@1"));
List<Activity> result = dao.doQuery(activityQuery);
assertEquals(1, result.size());
assertEquals("@1", result.get(0).getId());
}
@Test
public void shouldQueryByIdOr() {
List<Activity> activitys = getActivities();
InMemoryActivityDao dao = daoInstance();
dao.saveAll(activitys);
ActivityQuery<Activity> activityQuery = ActivityQuery.query("MyType2");
activityQuery.or().with(new IdSelection("@3"), new IdSelection("@4"));
List<Activity> result = dao.doQuery(activityQuery);
assertEquals(2, result.size());
assertEquals("@3", result.get(0).getId());
assertEquals("@4", result.get(1).getId());
}
@Test
public void shouldQueryByIdAnd() {
List<Activity> activitys = getActivities();
InMemoryActivityDao dao = daoInstance();
dao.saveAll(activitys);
ActivityQuery<Activity> activityQuery = ActivityQuery.query("MyType2");
activityQuery.and().with(new IdSelection("@3"), new NameSelection("Activity 3", es()));
List<Activity> result = dao.doQuery(activityQuery);
assertEquals(1, result.size());
assertEquals("@3", result.get(0).getId());
}
@Test
public void shouldNotQueryByIdAnd() {
List<Activity> activitys = getActivities();
InMemoryActivityDao dao = daoInstance();
dao.saveAll(activitys);
ActivityQuery<Activity> activityQuery = ActivityQuery.query("MyType1");
activityQuery.and().with(new IdSelection("@3"), new NameSelection("@4", es()));
List<Activity> result = dao.doQuery(activityQuery);
assertEquals(0, result.size());
}
@Test
public void shouldQueryByParameter() {
List<Activity> activitys = getActivities();
activitys.add(getBallActivity());
InMemoryActivityDao dao = daoInstance();
dao.saveAll(activitys);
ActivityQuery<Activity> ballQuery = ActivityQuery.query("Ball");
ballQuery.and().with(
//
stringSelection("parameters", "color", "red", es()),
booleanSelection("parameters", "forChildren", true), floatSelection("parameters", "diameter", 22.0));
List<Activity> result = dao.doQuery(ballQuery);
assertEquals(1, result.size());
}
@Test
public void shouldQueryByListParameter() {
List<Activity> activitys = getActivities();
activitys.add(getBallActivity());
InMemoryActivityDao dao = daoInstance();
dao.saveAll(activitys);
ActivityQuery<Activity> ballQuery;
List<Activity> result;
// string list
{
ballQuery = ActivityQuery.query("Ball");
ballQuery.and().with(stringListSelection("parameters", "stringListValues", Arrays.asList("a", "z")));
result = dao.doQuery(ballQuery);
assertEquals(0, result.size());
ballQuery = ActivityQuery.query("Ball");
ballQuery.and().with(stringListSelection("parameters", "stringListValues", Arrays.asList("a")));
result = dao.doQuery(ballQuery);
assertEquals(1, result.size());
ballQuery = ActivityQuery.query("Ball");
ballQuery.and().with(stringListSelection("parameters", "stringListValues", Arrays.asList("c", "b", "a")));
result = dao.doQuery(ballQuery);
assertEquals(1, result.size());
}
// integer list
{
ballQuery = ActivityQuery.query("Ball");
ballQuery.and().with(integerListSelection("parameters", "intListValues", Arrays.asList(1, 5)));
result = dao.doQuery(ballQuery);
assertEquals(0, result.size());
ballQuery = ActivityQuery.query("Ball");
ballQuery.and().with(integerListSelection("parameters", "intListValues", Arrays.asList(1)));
result = dao.doQuery(ballQuery);
assertEquals(1, result.size());
ballQuery = ActivityQuery.query("Ball");
ballQuery.and().with(integerListSelection("parameters", "intListValues", Arrays.asList(3, 2, 1)));
result = dao.doQuery(ballQuery);
assertEquals(1, result.size());
}
// float list
{
ballQuery = ActivityQuery.query("Ball");
ballQuery.and().with(floatListSelection("parameters", "floatListValues", Arrays.asList(4.0, 8.0)));
result = dao.doQuery(ballQuery);
assertEquals(0, result.size());
ballQuery = ActivityQuery.query("Ball");
ballQuery.and().with(floatListSelection("parameters", "floatListValues", Arrays.asList(4.0)));
result = dao.doQuery(ballQuery);
assertEquals(1, result.size());
ballQuery = ActivityQuery.query("Ball");
ballQuery.and().with(floatListSelection("parameters", "floatListValues", Arrays.asList(6.2, 5.1, 4.0)));
result = dao.doQuery(ballQuery);
assertEquals(1, result.size());
}
// long list
{
ballQuery = ActivityQuery.query("Ball");
ballQuery.and().with(longListSelection("parameters", "longListValues", Arrays.asList(8L, 11L)));
result = dao.doQuery(ballQuery);
assertEquals(0, result.size());
ballQuery = ActivityQuery.query("Ball");
ballQuery.and().with(longListSelection("parameters", "longListValues", Arrays.asList(8L)));
result = dao.doQuery(ballQuery);
assertEquals(1, result.size());
ballQuery = ActivityQuery.query("Ball");
ballQuery.and().with(longListSelection("parameters", "longListValues", Arrays.asList(10L, 9L, 8L)));
result = dao.doQuery(ballQuery);
assertEquals(1, result.size());
}
}
@Test
public void shouldQueryByNullParameter1() {
List<Activity> activitys = getActivities();
activitys.add(getBallActivity());
InMemoryActivityDao dao = daoInstance();
dao.saveAll(activitys);
ActivityQuery<Activity> ballQuery = ActivityQuery.query("Ball");
ballQuery.and().with( //
ParameterSelection.nullSelection("parameters", "color"));
List<Activity> result = dao.doQuery(ballQuery);
assertEquals(0, result.size());
}
@Test
public void shouldQueryByNullParameter2() {
List<Activity> activitys = getActivities();
activitys.add(getBallActivity());
InMemoryActivityDao dao = daoInstance();
dao.saveAll(activitys);
ActivityQuery<Activity> ballQuery = ActivityQuery.query("Ball");
ballQuery.and().with( //
ParameterSelection.nullSelection("parameters", "weight"));
List<Activity> result = dao.doQuery(ballQuery);
assertEquals(1, result.size());
}
@Test
public void shouldQueryByNullParameter3() {
List<Activity> activitys = getActivities();
activitys.add(getBallActivity());
InMemoryActivityDao dao = daoInstance();
dao.saveAll(activitys);
ActivityQuery<Activity> ballQuery = ActivityQuery.query("Ball");
ballQuery.and().with( //
ParameterSelection.nullSelection("parameters", "weight"));
List<Activity> result = dao.doQuery(ballQuery);
assertEquals(1, result.size());
}
@Test
public void shouldQueryByName() {
List<Activity> activitys = getActivities();
activitys.add(getBallActivity());
InMemoryActivityDao dao = daoInstance();
dao.saveAll(activitys);
ActivityQuery<Activity> ballQuery = ActivityQuery.query("Ball");
ballQuery.with(new NameSelection("ball ", ci()));
List<Activity> result = dao.doQuery(ballQuery);
assertEquals(1, result.size());
}
private Activity getBallActivity() {
Activity res1 = new Activity("childrensBall", "Ball 1", "Ball");
Version.setInitialVersionFor(res1, "test");
ParameterBag bag = new ParameterBag("parameters", "Ball Details", "Parameters");
bag.addParameter(new StringParameter("color", "Color", "red"));
bag.addParameter(new BooleanParameter("forChildren", "Color", true));
bag.addParameter(new FloatParameter("diameter", "Color", 22.0));
bag.addParameter(
new StringListParameter("stringListValues", "List of String Values", Arrays.asList("a", "b", "c")));
bag.addParameter(new IntegerListParameter("intListValues", "List of Integer Values", Arrays.asList(1, 2, 3)));
bag.addParameter(
new FloatListParameter("floatListValues", "List of Float Values", Arrays.asList(4.0, 5.1, 6.2)));
bag.addParameter(new LongListParameter("longListValues", "List of Long Values", Arrays.asList(8L, 9L, 10L)));
res1.addParameterBag(bag);
return res1;
}
private List<Activity> getActivities() {
Activity res1 = ModelGenerator.createActivity("@1", "Activity 1", "MyType1");
Activity res2 = ModelGenerator.createActivity("@2", "Activity 2", "MyType1");
Activity res3 = ModelGenerator.createActivity("@3", "Activity 3", "MyType2");
Activity res4 = ModelGenerator.createActivity("@4", "Activity 4", "MyType2");
Activity res5 = ModelGenerator.createActivity("@5", "Activity 5", "MyType3");
Activity res6 = ModelGenerator.createActivity("@6", "Activity 6", "MyType3");
List<Activity> activitys = new ArrayList<>();
activitys.add(res1);
activitys.add(res2);
activitys.add(res3);
activitys.add(res4);
activitys.add(res5);
activitys.add(res6);
for (Activity activity : activitys) {
Version.setInitialVersionFor(activity, "test");
}
return activitys;
}
}

View File

@ -100,7 +100,7 @@ public class InMemoryOrderQueryTest {
dao.saveAll(orders);
OrderQuery<Order> orderQuery = OrderQuery.query("MyType2");
orderQuery.and().with(new IdSelection("@3"), new NameSelection("Res 3", es()));
orderQuery.and().with(new IdSelection("@3"), new NameSelection("Order 3", es()));
List<Order> result = dao.doQuery(orderQuery);
assertEquals(1, result.size());
@ -285,7 +285,7 @@ public class InMemoryOrderQueryTest {
private Order getBallOrder() {
Order o1 = new Order("childrensBall", "Ball 1", "Ball");
o1.setVersion(new Version(o1.getLocator(), 0, "ModelGenerator", false));
Version.setInitialVersionFor(o1, "test");
ParameterBag bag = new ParameterBag("parameters", "Ball Details", "Parameters");
bag.addParameter(new StringParameter("color", "Color", "red"));
bag.addParameter(new BooleanParameter("forChildren", "Color", true));
@ -301,12 +301,12 @@ public class InMemoryOrderQueryTest {
}
private List<Order> getOrders() {
Order res1 = ModelGenerator.createOrder("@1", "Res 1", "MyType1", new Date(), State.CREATED);
Order res2 = ModelGenerator.createOrder("@2", "Res 2", "MyType1", new Date(), State.CREATED);
Order res3 = ModelGenerator.createOrder("@3", "Res 3", "MyType2", new Date(), State.CREATED);
Order res4 = ModelGenerator.createOrder("@4", "Res 4", "MyType2", new Date(), State.CREATED);
Order res5 = ModelGenerator.createOrder("@5", "Res 5", "MyType3", new Date(), State.CREATED);
Order res6 = ModelGenerator.createOrder("@6", "Res 6", "MyType3", new Date(), State.CREATED);
Order res1 = ModelGenerator.createOrder("@1", "Order 1", "MyType1", new Date(), State.CREATED);
Order res2 = ModelGenerator.createOrder("@2", "Order 2", "MyType1", new Date(), State.CREATED);
Order res3 = ModelGenerator.createOrder("@3", "Order 3", "MyType2", new Date(), State.CREATED);
Order res4 = ModelGenerator.createOrder("@4", "Order 4", "MyType2", new Date(), State.CREATED);
Order res5 = ModelGenerator.createOrder("@5", "Order 5", "MyType3", new Date(), State.CREATED);
Order res6 = ModelGenerator.createOrder("@6", "Order 6", "MyType3", new Date(), State.CREATED);
List<Order> orders = new ArrayList<>();
orders.add(res1);
orders.add(res2);
@ -314,6 +314,10 @@ public class InMemoryOrderQueryTest {
orders.add(res4);
orders.add(res5);
orders.add(res6);
for (Order order : orders) {
Version.setInitialVersionFor(order, "test");
}
return orders;
}
}

View File

@ -264,7 +264,7 @@ public class InMemoryResourceQueryTest {
private Resource getBallResource() {
Resource res1 = new Resource("childrensBall", "Ball 1", "Ball");
res1.setVersion(new Version(res1.getLocator(), 0, "ModelGenerator", false));
Version.setInitialVersionFor(res1, "test");
ParameterBag bag = new ParameterBag("parameters", "Ball Details", "Parameters");
bag.addParameter(new StringParameter("color", "Color", "red"));
bag.addParameter(new BooleanParameter("forChildren", "Color", true));
@ -293,11 +293,11 @@ public class InMemoryResourceQueryTest {
resources.add(res4);
resources.add(res5);
resources.add(res6);
for (Resource resource : resources) {
resource.setVersion(new Version(resource.getLocator(), 0, "Test", false));
Version.setInitialVersionFor(resource, "test");
}
return resources;
}
}

View File

@ -192,6 +192,8 @@ public class Order extends GroupedParameterizedElement implements StrolchRootEle
builder.append(this.state);
builder.append(", date=");
builder.append(ISO8601FormatFactory.getInstance().formatDate(this.date));
builder.append(", version=");
builder.append(this.version);
builder.append("]");
return builder.toString();

View File

@ -203,7 +203,8 @@ public class Resource extends GroupedParameterizedElement implements StrolchRoot
builder.append(this.name);
builder.append(", type=");
builder.append(this.type);
builder.append("]");
builder.append(", version=");
builder.append(this.version);
return builder.toString();
}

View File

@ -4,6 +4,7 @@ import java.text.MessageFormat;
import java.util.Date;
import li.strolch.utils.dbc.DBC;
import li.strolch.utils.iso8601.ISO8601FormatFactory;
/**
* <p>
@ -159,7 +160,7 @@ public class Version {
builder.append(", createdBy=");
builder.append(this.createdBy);
builder.append(", createdAt=");
builder.append(this.createdAt);
builder.append(ISO8601FormatFactory.getInstance().formatDate(this.createdAt));
builder.append(", deleted=");
builder.append(this.deleted);
builder.append("]");

View File

@ -296,6 +296,10 @@ public class Activity extends GroupedParameterizedElement
builder.append(this.getStart());
builder.append(", end=");
builder.append(this.getEnd());
if (isRootElement()) {
builder.append(", version=");
builder.append(this.version);
}
builder.append("]");
return builder.toString();
}

View File

@ -53,10 +53,11 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
@Override
public boolean hasElement(String type, String id) {
String sql = "select count(*) from " + getTableName() + " where type = ? and id = ?";
String sql = "select count(*) from " + getTableName() + " where type = ? and id = ? and latest = true";
try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) {
statement.setString(1, type);
statement.setString(2, id);
try (ResultSet result = statement.executeQuery()) {
result.next();
long numberOfElements = result.getLong(1);
@ -68,6 +69,7 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
String msg = MessageFormat.format("Non unique number of elements with type {0} and id {1}", type, id);
throw new StrolchPersistenceException(msg);
}
} catch (SQLException e) {
throw new StrolchPersistenceException("Failed to query size due to: " + e.getMessage(), e);
}
@ -75,12 +77,14 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
@Override
public long querySize() {
String sql = "select count(*) from " + getTableName();
String sql = "select count(*) from " + getTableName() + " where latest = true";
try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) {
try (ResultSet result = statement.executeQuery()) {
result.next();
return result.getLong(1);
}
} catch (SQLException e) {
throw new StrolchPersistenceException("Failed to query size due to: " + e.getMessage(), e);
}
@ -88,13 +92,15 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
@Override
public long querySize(String type) {
String sql = "select count(*) from " + getTableName() + " where type = ?";
String sql = "select count(*) from " + getTableName() + " where type = ? and latest = true";
try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) {
statement.setString(1, type);
try (ResultSet result = statement.executeQuery()) {
result.next();
return result.getLong(1);
}
} catch (SQLException e) {
throw new StrolchPersistenceException("Failed to query size due to: " + e.getMessage(), e);
}
@ -105,13 +111,15 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
Set<String> keySet = new HashSet<>();
String sql = "select id from " + getTableName();
String sql = "select id from " + getTableName() + " where latest = true";
try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) {
try (ResultSet result = statement.executeQuery()) {
while (result.next()) {
keySet.add(result.getString("id"));
}
}
} catch (SQLException e) {
throw new StrolchPersistenceException("Failed to query key set due to: " + e.getMessage(), e);
}
@ -123,14 +131,16 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
public Set<String> queryKeySet(String type) {
Set<String> keySet = new HashSet<>();
String sql = "select id from " + getTableName() + " where type = ?";
String sql = "select id from " + getTableName() + " where type = ? and latest = true";
try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) {
statement.setString(1, type);
try (ResultSet result = statement.executeQuery()) {
while (result.next()) {
keySet.add(result.getString("id"));
}
}
} catch (SQLException e) {
throw new StrolchPersistenceException("Failed to query key set due to: " + e.getMessage(), e);
}
@ -142,13 +152,15 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
public Set<String> queryTypes() {
Set<String> keySet = new HashSet<>();
String sql = "select distinct type from " + getTableName();
String sql = "select distinct type from " + getTableName() + " where latest = true";
try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) {
try (ResultSet result = statement.executeQuery()) {
while (result.next()) {
keySet.add(result.getString("type"));
}
}
} catch (SQLException e) {
throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e);
}
@ -159,10 +171,12 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
@Override
public T queryBy(String type, String id) {
String sql = "select id, name, type, asxml from " + getTableName() + " where id = ? and type = ?";
String sql = "select id, name, type, asxml from " + getTableName()
+ " where type = ? and id = ? and latest = true";
try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) {
statement.setString(1, id);
statement.setString(2, type);
statement.setString(1, type);
statement.setString(2, id);
try (ResultSet result = statement.executeQuery()) {
if (!result.next()) {
return null;
@ -174,6 +188,7 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
throw new StrolchPersistenceException("Non unique result for query: " + sql);
return t;
}
} catch (SQLException e) {
throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e);
}
@ -181,22 +196,88 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
@Override
public T queryBy(String type, String id, int version) {
// TODO Auto-generated method stub
return null;
String sql = "select id, name, type, asxml from " + getTableName()
+ " where type = ? and id = ? and version = ?";
try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) {
statement.setString(1, type);
statement.setString(2, id);
statement.setInt(3, version);
try (ResultSet result = statement.executeQuery()) {
if (!result.next()) {
return null;
}
SQLXML sqlxml = result.getSQLXML("asxml");
T t = parseFromXml(id, type, sqlxml);
if (result.next())
throw new StrolchPersistenceException("Non unique result for query: " + sql);
return t;
}
} catch (SQLException e) {
throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e);
}
}
@Override
public List<T> queryVersionsFor(String type, String id) {
// TODO Auto-generated method stub
return null;
String sql = "select id, name, type, asxml from " + getTableName()
+ " where type = ? and id = ? order by version";
List<T> list = new ArrayList<>(1);
try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) {
statement.setString(1, type);
statement.setString(2, id);
try (ResultSet result = statement.executeQuery()) {
while (result.next()) {
SQLXML sqlxml = result.getSQLXML("asxml");
T t = parseFromXml(id, type, sqlxml);
if (result.next())
throw new StrolchPersistenceException("Non unique result for query: " + sql);
list.add(t);
}
return list;
}
} catch (SQLException e) {
throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e);
}
}
@Override
public long queryVersionsSizeFor(String type, String id) {
String sql = "select count(*) from " + getTableName() + " where type = ? and id = ?";
try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) {
statement.setString(1, type);
statement.setString(2, id);
try (ResultSet result = statement.executeQuery()) {
result.next();
return result.getLong(1);
}
} catch (SQLException e) {
throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e);
}
}
@Override
public List<T> queryAll() {
List<T> list = new ArrayList<>();
String sql = "select id, name, type, asxml from " + getTableName();
String sql = "select id, name, type, asxml from " + getTableName() + " where latest = true";
try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) {
try (ResultSet result = statement.executeQuery()) {
while (result.next()) {
String id = result.getString("id");
@ -205,21 +286,24 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
T t = parseFromXml(id, type, sqlxml);
list.add(t);
}
return list;
}
} catch (SQLException e) {
throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e);
}
return list;
}
@Override
public List<T> queryAll(String type) {
List<T> list = new ArrayList<>();
String sql = "select id, name, type, asxml from " + getTableName() + " where type = ?";
String sql = "select id, name, type, asxml from " + getTableName() + " where type = ? and latest = true";
try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) {
statement.setString(1, type);
try (ResultSet result = statement.executeQuery()) {
while (result.next()) {
String id = result.getString("id");
@ -227,16 +311,17 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
T t = parseFromXml(id, type, sqlxml);
list.add(t);
}
return list;
}
} catch (SQLException e) {
throw new StrolchPersistenceException("Failed to query types due to: " + e.getMessage(), e);
}
return list;
}
@Override
public void save(final T res) {
public void save(T res) {
this.commands.add(txResult -> {
internalSave(res);
txResult.incCreated(1);
@ -244,7 +329,7 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
}
@Override
public void saveAll(final List<T> elements) {
public void saveAll(List<T> elements) {
this.commands.add(txResult -> {
for (T element : elements) {
internalSave(element);
@ -254,7 +339,7 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
}
@Override
public void update(final T element) {
public void update(T element) {
this.commands.add(txResult -> {
internalUpdate(element);
txResult.incUpdated(1);
@ -262,7 +347,7 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
}
@Override
public void updateAll(final List<T> elements) {
public void updateAll(List<T> elements) {
this.commands.add(txResult -> {
for (T element : elements) {
internalUpdate(element);
@ -272,7 +357,7 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
}
@Override
public void remove(final T element) {
public void remove(T element) {
this.commands.add(txResult -> {
internalRemove(element);
txResult.incDeleted(1);
@ -280,7 +365,7 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
}
@Override
public void removeAll(final List<T> elements) {
public void removeAll(List<T> elements) {
this.commands.add(txResult -> {
for (T element : elements) {
internalRemove(element);
@ -295,7 +380,7 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
final long toRemove = querySize();
this.commands.add(txResult -> {
internalRemoveAll(toRemove);
internalRemoveAll();
txResult.incDeleted(toRemove);
});
@ -303,12 +388,12 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
}
@Override
public long removeAllBy(final String type) {
public long removeAllBy(String type) {
final long toRemove = querySize(type);
long toRemove = querySize(type);
this.commands.add(txResult -> {
internalRemoveAllBy(toRemove, type);
internalRemoveAllBy(type);
txResult.incDeleted(toRemove);
});
@ -317,8 +402,10 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
@Override
public void removeVersion(T element) throws StrolchPersistenceException {
// TODO Auto-generated method stub
this.commands.add(txResult -> {
internalRemoveVersion(element);
txResult.incDeleted(1);
});
}
/**
@ -331,50 +418,102 @@ public abstract class PostgresqlDao<T extends StrolchRootElement> implements Str
*/
protected abstract void internalUpdate(T element);
protected void internalRemove(final T element) {
String sql = "delete from " + getTableName() + " where id = ?";
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
protected void internalRemove(T element) {
// first find out how many there are
long count = 0;
String sql = "select count(*) from " + getTableName() + " where type = ? and id = ?";
try (PreparedStatement statement = tx().getConnection().prepareStatement(sql)) {
statement.setString(1, element.getType());
statement.setString(2, element.getId());
try (ResultSet result = statement.executeQuery()) {
result.next();
count = result.getLong(1);
}
} catch (SQLException e) {
throw new StrolchPersistenceException(MessageFormat.format("Failed to remove {0} due to {1}",
element.getLocator(), e.getLocalizedMessage()), e);
}
if (count == 0) {
throw new StrolchPersistenceException(
MessageFormat.format("Failed to remove {0} as it does not exiset!", element.getLocator()));
}
sql = "delete from " + getTableName() + " where id = ?";
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
preparedStatement.setString(1, element.getId());
int modCount = preparedStatement.executeUpdate();
if (modCount != 1) {
String msg = "Expected to delete 1 element with id {0} but SQL statement modified {1} elements!";
msg = MessageFormat.format(msg, element.getId(), modCount);
if (modCount != count) {
String msg = "Expected to delete {0} element with id {1} but SQL statement deleted {2} elements!";
msg = MessageFormat.format(msg, count, element.getId(), modCount);
throw new StrolchPersistenceException(msg);
}
} catch (SQLException e) {
throw new StrolchPersistenceException(MessageFormat.format("Failed to remove {0} due to {2}",
throw new StrolchPersistenceException(MessageFormat.format("Failed to remove {0} due to {1}",
element.getLocator(), e.getLocalizedMessage()), e);
}
}
protected void internalRemoveAll(final long toRemove) {
String sql = "delete from " + getTableName();
private void internalRemoveVersion(T element) {
String sql = "delete from " + getTableName() + " where type = ? and id = ? and version = ? and latest = true";
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
preparedStatement.setString(1, element.getType());
preparedStatement.setString(2, element.getId());
preparedStatement.setInt(3, element.getVersion().getVersion());
int modCount = preparedStatement.executeUpdate();
if (modCount != toRemove) {
String msg = "Expected to delete {0} elements but SQL statement removed {1} elements!";
msg = MessageFormat.format(msg, toRemove, modCount);
if (modCount != 1) {
String msg = "Expected to delete 1 element with id {0} but SQL statement modified {1} elements! Verify that element {2} is the latest version!";
msg = MessageFormat.format(msg, element.getId(), modCount, element.getVersion());
throw new StrolchPersistenceException(msg);
}
//
sql = "update " + getTableName() + " set latest = true where type = ? and id = ? and version = ?";
try (PreparedStatement updateStmt = tx().getConnection().prepareStatement(sql)) {
int previousVersion = element.getVersion().getPreviousVersion();
updateStmt.setString(1, element.getType());
updateStmt.setString(2, element.getId());
updateStmt.setInt(3, previousVersion);
modCount = updateStmt.executeUpdate();
if (modCount != 1) {
String msg = "Expected to update 1 element with id {0} but SQL statement modified {1} elements! Verify that element {2} with version {3} exists!";
msg = MessageFormat.format(msg, element.getId(), modCount, element.getLocator(), previousVersion);
throw new StrolchPersistenceException(msg);
}
}
} catch (SQLException e) {
throw new StrolchPersistenceException(MessageFormat.format("Failed to remove version {0} due to {1}",
element.getLocator(), e.getLocalizedMessage()), e);
}
}
protected void internalRemoveAll() {
String sql = "delete from " + getTableName();
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
preparedStatement.executeUpdate();
} catch (SQLException e) {
throw new StrolchPersistenceException(
MessageFormat.format("Failed to remove all elements due to {0}", e.getLocalizedMessage()), e);
}
}
protected void internalRemoveAllBy(final long toRemove, String type) {
protected void internalRemoveAllBy(String type) {
String sql = "delete from " + getTableName() + " where type = ?";
try (PreparedStatement preparedStatement = tx().getConnection().prepareStatement(sql)) {
preparedStatement.setString(1, type);
int modCount = preparedStatement.executeUpdate();
if (modCount != toRemove) {
String msg = "Expected to delete {0} elements of type {1} but SQL statement removed {2} elements!";
msg = MessageFormat.format(msg, toRemove, type, modCount);
throw new StrolchPersistenceException(msg);
}
preparedStatement.executeUpdate();
} catch (SQLException e) {
throw new StrolchPersistenceException(MessageFormat

View File

@ -0,0 +1,89 @@
/*
* 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.persistence.postgresql.dao.test;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.text.MessageFormat;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.postgresql.Driver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import li.strolch.db.DbSchemaVersionCheck;
import li.strolch.persistence.postgresql.PostgreSqlPersistenceHandler;
import li.strolch.testbase.runtime.AbstractModelTest;
import li.strolch.testbase.runtime.RuntimeMock;
import li.strolch.utils.Version;
import li.strolch.utils.helper.StringHelper;
public class CachedVersioningDaoTest extends AbstractModelTest {
public static final String RUNTIME_PATH = "target/cachedStrolchRuntime/"; //$NON-NLS-1$
public static final String DB_STORE_PATH_DIR = "dbStore"; //$NON-NLS-1$
public static final String CONFIG_SRC = "src/test/resources/cachedruntimeVersioning"; //$NON-NLS-1$
public static final String DB_URL = "jdbc:postgresql://localhost/testdb"; //$NON-NLS-1$
public static final String DB_USERNAME = "testuser"; //$NON-NLS-1$
public static final String DB_PASSWORD = "test"; //$NON-NLS-1$
private static final Logger logger = LoggerFactory.getLogger(CachedVersioningDaoTest.class);
protected static RuntimeMock runtimeMock;
@Override
protected RuntimeMock getRuntimeMock() {
return runtimeMock;
}
@BeforeClass
public static void beforeClass() throws Exception {
dropSchema(DB_URL, DB_USERNAME, DB_PASSWORD);
File rootPath = new File(RUNTIME_PATH);
File configSrc = new File(CONFIG_SRC);
runtimeMock = new RuntimeMock();
runtimeMock.mockRuntime(rootPath, configSrc);
new File(rootPath, DB_STORE_PATH_DIR).mkdir();
runtimeMock.startContainer();
}
public static void dropSchema(String dbUrl, String dbUsername, String dbPassword) throws Exception {
if (!Driver.isRegistered())
Driver.register();
Version dbVersion = DbSchemaVersionCheck.getExpectedDbVersion(PostgreSqlPersistenceHandler.SCRIPT_PREFIX,
PostgreSqlPersistenceHandler.class);
logger.info(MessageFormat.format("Dropping schema for expected version {0}", dbVersion));
String sql = DbSchemaVersionCheck.getSql(PostgreSqlPersistenceHandler.SCRIPT_PREFIX,
PostgreSqlPersistenceHandler.class, dbVersion, "drop"); //$NON-NLS-1$
logger.info(StringHelper.NEW_LINE + sql);
try (Connection connection = DriverManager.getConnection(dbUrl, dbUsername, dbPassword)) {
connection.prepareStatement(sql).execute();
}
}
@AfterClass
public static void afterClass() {
if (runtimeMock != null)
runtimeMock.destroyRuntime();
}
}

View File

@ -40,9 +40,9 @@ public class RealmTest extends AbstractModelTest {
private static final String TESTUSER2 = "testuser2"; //$NON-NLS-1$
private static final String TESTUSER1 = "testuser1"; //$NON-NLS-1$
private static final String SECOND = "second"; //$NON-NLS-1$
private static final String TEST = "test"; //$NON-NLS-1$
private static final String FIRST = "first"; //$NON-NLS-1$
private static final String SECOND = "second"; //$NON-NLS-1$
public static final String RUNTIME_PATH = "target/realmtest/"; //$NON-NLS-1$
public static final String DB_STORE_PATH_DIR = "dbStore"; //$NON-NLS-1$

View File

@ -0,0 +1,62 @@
/*
* 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.persistence.postgresql.dao.test;
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_PASSWORD;
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_URL;
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.DB_USERNAME;
import static li.strolch.persistence.postgresql.dao.test.CachedDaoTest.dropSchema;
import java.io.File;
import li.strolch.testbase.runtime.AbstractModelTest;
import li.strolch.testbase.runtime.RuntimeMock;
import org.junit.AfterClass;
import org.junit.BeforeClass;
public class TransactionalVersioningDaoTest extends AbstractModelTest {
public static final String RUNTIME_PATH = "target/transactionalStrolchRuntime/"; //$NON-NLS-1$
public static final String DB_STORE_PATH_DIR = "dbStore"; //$NON-NLS-1$
public static final String CONFIG_SRC = "src/test/resources/transactionalruntimeVersioning"; //$NON-NLS-1$
protected static RuntimeMock runtimeMock;
@Override
protected RuntimeMock getRuntimeMock() {
return runtimeMock;
}
@BeforeClass
public static void beforeClass() throws Exception {
dropSchema(DB_URL, DB_USERNAME, DB_PASSWORD);
File rootPath = new File(RUNTIME_PATH);
File configSrc = new File(CONFIG_SRC);
runtimeMock = new RuntimeMock();
runtimeMock.mockRuntime(rootPath, configSrc);
new File(rootPath, DB_STORE_PATH_DIR).mkdir();
runtimeMock.startContainer();
}
@AfterClass
public static void afterClass() {
if (runtimeMock != null)
runtimeMock.destroyRuntime();
}
}

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<Privilege>
<Container>
<Parameters>
<!-- parameters for the container itself -->
<Parameter name="autoPersistOnUserChangesData" value="true" />
</Parameters>
<EncryptionHandler class="li.strolch.privilege.handler.DefaultEncryptionHandler">
<Parameters>
<Parameter name="hashAlgorithm" value="SHA-256" />
</Parameters>
</EncryptionHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler">
<Parameters>
<Parameter name="usersXmlFile" value="PrivilegeUsers.xml" />
<Parameter name="rolesXmlFile" value="PrivilegeRoles.xml" />
</Parameters>
</PersistenceHandler>
</Container>
<Policies>
<Policy name="DefaultPrivilege" class="li.strolch.privilege.policy.DefaultPrivilege" />
<Policy name="RoleAccessPrivilege" class="li.strolch.privilege.policy.RoleAccessPrivilege" />
<Policy name="UserAccessPrivilege" class="li.strolch.privilege.policy.UserAccessPrivilege" />
</Policies>
</Privilege>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<Roles>
<Role name="agent">
<Privilege name="li.strolch.privilege.handler.SystemUserAction" policy="DefaultPrivilege">
<Allow>li.strolch.agent.impl.StartRealms</Allow>
</Privilege>
</Role>
<Role name="AppUser">
<Privilege name="li.strolch.service.api.Service" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="li.strolch.model.query.StrolchQuery" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
</Role>
</Roles>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<Users>
<User userId="1" username="agent">
<State>SYSTEM</State>
<Roles>
<Role>agent</Role>
</Roles>
</User>
<User userId="2" username="test" password="9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08">
<Firstname>Application</Firstname>
<Lastname>Administrator</Lastname>
<State>ENABLED</State>
<Locale>en_GB</Locale>
<Roles>
<Role>AppUser</Role>
</Roles>
</User>
</Users>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<StrolchConfiguration>
<env id="dev">
<Runtime>
<applicationName>StrolchPersistenceTest</applicationName>
<Properties>
<verbose>true</verbose>
</Properties>
</Runtime>
<Component>
<name>PrivilegeHandler</name>
<api>li.strolch.runtime.privilege.PrivilegeHandler</api>
<impl>li.strolch.runtime.privilege.DefaultStrolchPrivilegeHandler</impl>
<Properties>
<privilegeConfigFile>PrivilegeConfig.xml</privilegeConfigFile>
</Properties>
</Component>
<Component>
<name>RealmHandler</name>
<api>li.strolch.agent.api.RealmHandler</api>
<impl>li.strolch.agent.impl.DefaultRealmHandler</impl>
<depends>PrivilegeHandler</depends>
<depends>PersistenceHandler</depends>
<Properties>
<dataStoreMode>CACHED</dataStoreMode>
<enableAuditTrail>true</enableAuditTrail>
<enableObserverUpdates>true</enableObserverUpdates>
<enableVersioning>true</enableVersioning>
</Properties>
</Component>
<Component>
<name>PersistenceHandler</name>
<api>li.strolch.persistence.api.PersistenceHandler</api>
<impl>li.strolch.persistence.postgresql.PostgreSqlPersistenceHandler</impl>
<Properties>
<allowSchemaCreation>true</allowSchemaCreation>
<allowSchemaDrop>true</allowSchemaDrop>
<db.url>jdbc:postgresql://localhost/testdb</db.url>
<db.username>testuser</db.username>
<db.password>test</db.password>
<db.pool.maximumPoolSize>1</db.pool.maximumPoolSize>
</Properties>
</Component>
</env>
</StrolchConfiguration>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<Privilege>
<Container>
<Parameters>
<!-- parameters for the container itself -->
<Parameter name="autoPersistOnUserChangesData" value="true" />
</Parameters>
<EncryptionHandler class="li.strolch.privilege.handler.DefaultEncryptionHandler">
<Parameters>
<Parameter name="hashAlgorithm" value="SHA-256" />
</Parameters>
</EncryptionHandler>
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler">
<Parameters>
<Parameter name="usersXmlFile" value="PrivilegeUsers.xml" />
<Parameter name="rolesXmlFile" value="PrivilegeRoles.xml" />
</Parameters>
</PersistenceHandler>
</Container>
<Policies>
<Policy name="DefaultPrivilege" class="li.strolch.privilege.policy.DefaultPrivilege" />
<Policy name="RoleAccessPrivilege" class="li.strolch.privilege.policy.RoleAccessPrivilege" />
<Policy name="UserAccessPrivilege" class="li.strolch.privilege.policy.UserAccessPrivilege" />
</Policies>
</Privilege>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<Roles>
<Role name="agent">
<Privilege name="li.strolch.privilege.handler.SystemUserAction" policy="DefaultPrivilege">
<Allow>li.strolch.agent.impl.StartRealms</Allow>
</Privilege>
</Role>
<Role name="AppUser">
<Privilege name="li.strolch.service.api.Service" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
<Privilege name="li.strolch.model.query.StrolchQuery" policy="DefaultPrivilege">
<AllAllowed>true</AllAllowed>
</Privilege>
</Role>
</Roles>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<Users>
<User userId="1" username="agent">
<State>SYSTEM</State>
<Roles>
<Role>agent</Role>
</Roles>
</User>
<User userId="2" username="test" password="9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08">
<Firstname>Application</Firstname>
<Lastname>Administrator</Lastname>
<State>ENABLED</State>
<Locale>en_GB</Locale>
<Roles>
<Role>AppUser</Role>
</Roles>
</User>
</Users>

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<StrolchConfiguration>
<env id="dev">
<Runtime>
<applicationName>StrolchPersistenceTest</applicationName>
<Properties>
<verbose>true</verbose>
</Properties>
</Runtime>
<Component>
<name>PrivilegeHandler</name>
<api>li.strolch.runtime.privilege.PrivilegeHandler</api>
<impl>li.strolch.runtime.privilege.DefaultStrolchPrivilegeHandler</impl>
<Properties>
<privilegeConfigFile>PrivilegeConfig.xml</privilegeConfigFile>
</Properties>
</Component>
<Component>
<name>RealmHandler</name>
<api>li.strolch.agent.api.RealmHandler</api>
<impl>li.strolch.agent.impl.DefaultRealmHandler</impl>
<depends>PrivilegeHandler</depends>
<depends>PersistenceHandler</depends>
<Properties>
<dataStoreMode>TRANSACTIONAL</dataStoreMode>
<enableAuditTrail>true</enableAuditTrail>
<enableVersioning>true</enableVersioning>
</Properties>
</Component>
<Component>
<name>PersistenceHandler</name>
<api>li.strolch.persistence.api.PersistenceHandler</api>
<impl>li.strolch.persistence.postgresql.PostgreSqlPersistenceHandler</impl>
<Properties>
<allowSchemaCreation>true</allowSchemaCreation>
<allowSchemaDrop>true</allowSchemaDrop>
<db.url>jdbc:postgresql://localhost/testdb</db.url>
<db.username>testuser</db.username>
<db.password>test</db.password>
<db.pool.maximumPoolSize>1</db.pool.maximumPoolSize>
</Properties>
</Component>
</env>
</StrolchConfiguration>

View File

@ -43,84 +43,72 @@ public abstract class AbstractModelTest {
@Test
public void shouldCreateOrders() {
OrderModelTestRunner testRunner = new OrderModelTestRunner(getRuntimeMock(), this.realmName);
testRunner.runCreateOrderTest();
}
@Test
public void shouldQueryOrderSizes() {
OrderModelTestRunner testRunner = new OrderModelTestRunner(getRuntimeMock(), this.realmName);
testRunner.runQuerySizeTest();
}
@Test
public void shouldOrderCrud() {
OrderModelTestRunner testRunner = new OrderModelTestRunner(getRuntimeMock(), this.realmName);
testRunner.runCrudTests();
}
@Test
public void shouldOrderPerformBulkOperations() {
OrderModelTestRunner testRunner = new OrderModelTestRunner(getRuntimeMock(), this.realmName);
testRunner.runBulkOperationTests();
}
@Test
public void shouldCreateResources() {
ResourceModelTestRunner testRunner = new ResourceModelTestRunner(getRuntimeMock(), this.realmName);
testRunner.runCreateResourceTest();
}
@Test
public void shouldQueryResourceSizes() {
ResourceModelTestRunner testRunner = new ResourceModelTestRunner(getRuntimeMock(), this.realmName);
testRunner.runQuerySizeTest();
}
@Test
public void shouldResourceCrud() {
ResourceModelTestRunner testRunner = new ResourceModelTestRunner(getRuntimeMock(), this.realmName);
testRunner.runCrudTests();
}
@Test
public void shouldResourcePerformBulkOperations() {
ResourceModelTestRunner testRunner = new ResourceModelTestRunner(getRuntimeMock(), this.realmName);
testRunner.runBulkOperationTests();
}
@Test
public void shouldCreateActivities() {
ActivityModelTestRunner testRunner = new ActivityModelTestRunner(getRuntimeMock(), this.realmName);
testRunner.runCreateActivityTest();
}
@Test
public void shouldQueryActivitySizes() {
ActivityModelTestRunner testRunner = new ActivityModelTestRunner(getRuntimeMock(), this.realmName);
testRunner.runQuerySizeTest();
}
@Test
public void shouldActivityCrud() {
ActivityModelTestRunner testRunner = new ActivityModelTestRunner(getRuntimeMock(), this.realmName);
testRunner.runCrudTests();
}
@Test
public void shouldActivityPerformBulkOperations() {
ActivityModelTestRunner testRunner = new ActivityModelTestRunner(getRuntimeMock(), this.realmName);
testRunner.runBulkOperationTests();
}

View File

@ -164,18 +164,16 @@ public class ActivityModelTestRunner {
activities.addAll(createActivities(activities.size(), 5, "@", "Further Activity", "MyType3"));
// sort them so we know which activity our objects are
Comparator<Activity> comparator = new Comparator<Activity>() {
@Override
public int compare(Activity o1, Activity o2) {
return o1.getId().compareTo(o2.getId());
}
};
Comparator<Activity> comparator = (o1, o2) -> o1.getId().compareTo(o2.getId());
Collections.sort(activities, comparator);
// first clear the map, so that we have a clean state
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
ActivityMap activityMap = tx.getActivityMap();
activityMap.removeAll(tx, activityMap.getAllElements(tx));
List<Activity> allElements = activityMap.getAllElements(tx);
long removed = activityMap.removeAll(tx);
assertEquals(allElements.size(), removed);
assertEquals(0, activityMap.querySize(tx));
tx.commitOnClose();
}

View File

@ -75,6 +75,10 @@ public class OrderModelTestRunner {
tx.getOrderMap().removeAll(tx, tx.getOrderMap().getAllElements(tx));
tx.commitOnClose();
}
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
long size = tx.getOrderMap().querySize(tx);
assertEquals("Should have 0 objects", 0, size);
}
// create three orders
Order order1 = createOrder("myTestOrder1", "Test Name", "QTestType1"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
@ -164,18 +168,16 @@ public class OrderModelTestRunner {
orders.addAll(createOrders(orders.size(), 5, "@", "Further Order", "MyType3"));
// sort them so we know which order our objects are
Comparator<Order> comparator = new Comparator<Order>() {
@Override
public int compare(Order o1, Order o2) {
return o1.getId().compareTo(o2.getId());
}
};
Comparator<Order> comparator = (o1, o2) -> o1.getId().compareTo(o2.getId());
Collections.sort(orders, comparator);
// first clear the map, so that we have a clean state
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
OrderMap orderMap = tx.getOrderMap();
orderMap.removeAll(tx, orderMap.getAllElements(tx));
List<Order> allElements = orderMap.getAllElements(tx);
long removed = orderMap.removeAll(tx);
assertEquals(allElements.size(), removed);
assertEquals(0, orderMap.querySize(tx));
tx.commitOnClose();
}

View File

@ -164,18 +164,16 @@ public class ResourceModelTestRunner {
resources.addAll(createResources(resources.size(), 5, "@", "Further Resource", "MyType3"));
// sort them so we know which order our objects are
Comparator<Resource> comparator = new Comparator<Resource>() {
@Override
public int compare(Resource o1, Resource o2) {
return o1.getId().compareTo(o2.getId());
}
};
Comparator<Resource> comparator = (o1, o2) -> o1.getId().compareTo(o2.getId());
Collections.sort(resources, comparator);
// first clear the map, so that we have a clean state
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
ResourceMap resourceMap = tx.getResourceMap();
resourceMap.removeAll(tx, resourceMap.getAllElements(tx));
List<Resource> allElements = resourceMap.getAllElements(tx);
long removed = resourceMap.removeAll(tx);
assertEquals(allElements.size(), removed);
assertEquals(0, resourceMap.querySize(tx));
tx.commitOnClose();
}
@ -201,7 +199,8 @@ public class ResourceModelTestRunner {
// now use the remove all by type
try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
tx.getResourceMap().removeAllBy(tx, "MyType3");
long removed = tx.getResourceMap().removeAllBy(tx, "MyType3");
assertEquals(5, removed);
tx.commitOnClose();
}

View File

@ -5,6 +5,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import java.util.List;
@ -13,6 +14,7 @@ import li.strolch.model.ModelGenerator;
import li.strolch.model.Resource;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.privilege.model.Certificate;
import li.strolch.runtime.StrolchConstants;
import li.strolch.runtime.privilege.PrivilegeHandler;
public class VersioningTestRunner {
@ -28,6 +30,7 @@ public class VersioningTestRunner {
}
public void runTestsForVersioning() {
assumeTrue(runtimeMock.getRealm(StrolchConstants.DEFAULT_REALM).isVersioningEnabled());
ComponentContainer container = runtimeMock.getContainer();