[Fix] Fixed bug where changed element is not returned in streams

This commit is contained in:
Robert von Burg 2018-06-22 11:38:24 +02:00
parent acf3b3ff6c
commit bbf021f73b
6 changed files with 198 additions and 14 deletions

View File

@ -514,17 +514,29 @@ public abstract class AbstractTransaction implements StrolchTransaction {
@Override
public Stream<Resource> streamResources(String... types) {
return getResourceMap().stream(this, types);
return getResourceMap().stream(this, types).map(e -> {
// perhaps the element was changed before, so we check if it is in the filter first
Resource element = getElementFromFilter(Tags.RESOURCE, e.getLocator());
return element == null ? e : element;
});
}
@Override
public Stream<Order> streamOrders(String... types) {
return getOrderMap().stream(this, types);
return getOrderMap().stream(this, types).map(e -> {
// perhaps the element was changed before, so we check if it is in the filter first
Order element = getElementFromFilter(Tags.ORDER, e.getLocator());
return element == null ? e : element;
});
}
@Override
public Stream<Activity> streamActivities(String... types) {
return getActivityMap().stream(this, types);
return getActivityMap().stream(this, types).map(e -> {
// perhaps the element was changed before, so we check if it is in the filter first
Activity element = getElementFromFilter(Tags.ACTIVITY, e.getLocator());
return element == null ? e : element;
});
}
@Override

View File

@ -276,7 +276,7 @@ public class StrolchSearchTest {
Map<String, State> states = new ActivitySearch()
.types().where(state().isEqualTo(State.PLANNING).and(name(isEqualTo("Activity"))).asActivityExp())
.types().where(state().isEqualTo(State.PLANNING).and(name(isEqualTo("Activity"))).asActivity())
.search(tx).toMap(Activity::getId, Activity::getState);

View File

@ -39,6 +39,7 @@ public class Order extends AbstractStrolchRootElement implements StrolchRootElem
private static final long serialVersionUID = 0L;
protected Locator locator;
protected Version version;
protected Date date;
protected State state;
@ -204,9 +205,12 @@ public class Order extends AbstractStrolchRootElement implements StrolchRootElem
@Override
public Locator getLocator() {
LocatorBuilder lb = new LocatorBuilder();
fillLocator(lb);
return lb.build();
if (this.locator == null) {
LocatorBuilder lb = new LocatorBuilder();
fillLocator(lb);
this.locator = lb.build();
}
return this.locator;
}
@Override

View File

@ -41,6 +41,7 @@ public class Resource extends AbstractStrolchRootElement implements StrolchRootE
private static final long serialVersionUID = 0L;
protected Locator locator;
protected Version version;
protected Map<String, StrolchTimedState<IValue<?>>> timedStateMap;
protected PolicyDefs policyDefs;
@ -240,9 +241,12 @@ public class Resource extends AbstractStrolchRootElement implements StrolchRootE
@Override
public Locator getLocator() {
LocatorBuilder lb = new LocatorBuilder();
fillLocator(lb);
return lb.build();
if (this.locator == null) {
LocatorBuilder lb = new LocatorBuilder();
fillLocator(lb);
this.locator = lb.build();
}
return this.locator;
}
@Override

View File

@ -42,7 +42,8 @@ public class Activity extends AbstractStrolchRootElement
private static final long serialVersionUID = 1L;
private Version version;
protected Locator locator;
protected Version version;
protected Activity parent;
protected TimeOrdering timeOrdering;
@ -453,9 +454,12 @@ public class Activity extends AbstractStrolchRootElement
@Override
public Locator getLocator() {
LocatorBuilder lb = new LocatorBuilder();
fillLocator(lb);
return lb.build();
if (this.locator == null) {
LocatorBuilder lb = new LocatorBuilder();
fillLocator(lb);
this.locator = lb.build();
}
return this.locator;
}
@Override

View File

@ -0,0 +1,160 @@
/*
* Copyright 2015 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.service;
import static org.junit.Assert.*;
import java.util.List;
import li.strolch.model.ModelGenerator;
import li.strolch.model.Resource;
import li.strolch.persistence.api.AddResourceCommand;
import li.strolch.persistence.api.RemoveResourceCommand;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.persistence.api.UpdateResourceCommand;
import li.strolch.search.ResourceSearch;
import li.strolch.service.api.AbstractService;
import li.strolch.service.api.Service;
import li.strolch.service.api.ServiceArgument;
import li.strolch.service.api.ServiceResult;
import li.strolch.service.test.AbstractRealmServiceTest;
import li.strolch.utils.dbc.DBC;
import org.junit.Assert;
import org.junit.Test;
public class TxModifyTest extends AbstractRealmServiceTest<ServiceArgument, ServiceResult> {
private Class<? extends Service<ServiceArgument, ServiceResult>> svcClass;
@Test
public void shouldFindModifiedElementInSearch() {
this.svcClass = ModifyAndSearchService.class;
runServiceInAllRealmTypes();
}
@Test
public void shouldRollbackSuccessfully() {
this.svcClass = RollbackService.class;
runServiceInAllRealmTypes();
}
@Override
protected Class<? extends Service<ServiceArgument, ServiceResult>> getSvcClass() {
return this.svcClass;
}
@Override
protected ServiceArgument getArgInstance() {
return new ServiceArgument();
}
public static class ModifyAndSearchService extends AbstractService<ServiceArgument, ServiceResult> {
private static final long serialVersionUID = 1L;
@Override
protected ServiceResult getResultInstance() {
return new ServiceResult();
}
@Override
public ServiceArgument getArgumentInstance() {
return new ServiceArgument();
}
@Override
protected ServiceResult internalDoService(ServiceArgument arg) throws Exception {
String type = "Car";
String id = "car001";
Resource resource = ModelGenerator.createResource(id, id, type);
try (StrolchTransaction tx = openTx(arg.realm)) {
tx.add(resource);
tx.commitOnClose();
}
try (StrolchTransaction tx = openTx(arg.realm)) {
// get the element
Resource car001 = tx.getResourceBy(type, id, true);
// modify
car001.setName("Changed!");
tx.update(car001);
// search for all cars
List<Resource> cars = new ResourceSearch().types(type).search(tx).cloneIfReadOnly().toList();
assertEquals(1, cars.size());
assertSame("We didn't get the same car!", car001, cars.get(0));
// also validate get returns the same instance
Resource carByGet = tx.getResourceBy(type, id, true);
assertSame("We didn't get the same car!", car001, carByGet);
// also validate find returns the same instance
Resource carByFind = tx.findElement(car001.getLocator());
assertSame("We didn't get the same car!", car001, carByFind);
tx.commitOnClose();
}
return ServiceResult.success();
}
}
public static class RollbackService extends AbstractService<ServiceArgument, ServiceResult> {
private static final long serialVersionUID = 1L;
@Override
protected ServiceResult getResultInstance() {
return new ServiceResult();
}
@Override
public ServiceArgument getArgumentInstance() {
return new ServiceArgument();
}
@Override
protected ServiceResult internalDoService(ServiceArgument arg) throws Exception {
String type = "Car";
String id = "car002";
Resource resource = ModelGenerator.createResource(id, id, type);
try (StrolchTransaction tx = openTx(arg.realm)) {
tx.add(resource);
tx.commitOnClose();
}
try (StrolchTransaction tx = openTx(arg.realm)) {
Resource car001 = tx.getResourceBy(type, id, true);
// modify
car001.setName("Changed!");
tx.update(car001);
tx.rollbackOnClose();
}
// now make sure the element was not changed
try (StrolchTransaction tx = openTx(arg.realm)) {
Resource car001 = tx.getResourceBy(type, id, true);
assertEquals("Expected name not to be changed in rollback of TX!", id, car001.getName());
}
return ServiceResult.success();
}
}
}