blob: a218aca69b95162b8ce11bb398f8e431655653f4 [file] [log] [blame]
/********************************************************************************
* Copyright (c) 2015-2019 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
********************************************************************************/
package org.eclipse.mdm.businessobjects.service;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import javax.ejb.Stateless;
import org.eclipse.mdm.api.base.model.ContextType;
import org.eclipse.mdm.api.base.model.Entity;
import org.eclipse.mdm.api.base.model.Environment;
import org.eclipse.mdm.api.dflt.ApplicationContext;
import org.eclipse.mdm.api.dflt.EntityManager;
import org.eclipse.mdm.api.dflt.model.EntityFactory;
import org.eclipse.mdm.api.dflt.model.TemplateAttribute;
import org.eclipse.mdm.api.dflt.model.TemplateComponent;
import org.eclipse.mdm.api.dflt.model.TemplateRoot;
import org.eclipse.mdm.api.dflt.model.TemplateSensor;
import org.eclipse.mdm.api.dflt.model.TemplateTest;
import org.eclipse.mdm.api.dflt.model.TemplateTestStep;
import org.eclipse.mdm.api.dflt.model.TemplateTestStepUsage;
import org.eclipse.mdm.businessobjects.utils.EntityNotFoundException;
import org.eclipse.mdm.businessobjects.utils.EntityNotFoundException.Type;
import io.vavr.Tuple;
import io.vavr.Value;
import io.vavr.control.Try;
/**
* {@link TemplateRoot} service handling corresponding operations
*
* @author Philipp Schweinbenz, science+computing AG Tuebingen (Atos SE)
* @author Alexander Nehmer, science+computing AG Tuebingen (Atos SE)
*
*/
@Stateless
public class TemplateService extends EntityService {
/**
* Create new version of {@link TemplateTest} with given name. The link linked
* {@link TemplateTestStep}s are copied.
*
* @param sourceNameSupplier a {@link Value} with the source name (MDM
* {@link Environment} name)
* @param name name of entity to create new version of
* @return new version of the {@link TemplateTestStep} with the given name
*/
@SuppressWarnings("unchecked")
public <T extends Entity> Try<T> createTplTestVersion(String sourceName, String name) {
return Try.of(() -> {
List<TemplateTest> tplTests = getEntityManager(sourceName)
.mapTry(em -> em.loadAll(TemplateTest.class, name)).get();
if (tplTests.isEmpty()) {
throw new EntityNotFoundException(TemplateTestStep.class, name, Type.NAME);
}
ApplicationContext appContext = connectorService.getContextByName(sourceName);
EntityFactory entityFactory = appContext.getEntityFactory().get();
EntityManager entityManager = appContext.getEntityManager().get();
// get latest version
Comparator<TemplateTest> versionComparator = Comparator.comparing(TemplateTest::getVersion);
TemplateTest latestTplTest = tplTests.stream().max(versionComparator).get();
TemplateTest newTplTest = entityFactory.createTemplateTest(latestTplTest.getName());
newTplTest.setVersion(latestTplTest.getVersion() + 1);
Set<Entity> entities = (Set<Entity>) DataAccessHelper.execute(entityManager,
Tuple.of(newTplTest, DataAccessHelper.CREATE));
// set TplTestSteps as in latestVersion
for (TemplateTestStepUsage tplTestStepUsage : latestTplTest.getTemplateTestStepUsages()) {
TemplateTestStepUsage newUsage = entityFactory.createTemplateTestStepUsage(tplTestStepUsage.getName(),
newTplTest, tplTestStepUsage.getTemplateTestStep());
DataAccessHelper.execute(entityManager, Tuple.of(newUsage, DataAccessHelper.CREATE));
}
return (T) entities.toArray()[0];
});
}
/**
* Create new version of {@link TemplateTestStep} with given name. The linked
* TplRoots are copied from the given {@link TemplateTestStep}
*
* @param sourceNameSupplier a {@link Value} with the source name (MDM
* {@link Environment} name)
* @param name name of entity to create new version of
* @return new version of the {@link TemplateTestStep} with the given name
*/
@SuppressWarnings("unchecked")
public <T extends Entity> Try<T> createTplTestStepVersion(String sourceName, String name) {
return Try.of(() -> {
List<TemplateTestStep> tplTestSteps = getEntityManager(sourceName)
.mapTry(em -> em.loadAll(TemplateTestStep.class, name)).get();
if (tplTestSteps.isEmpty()) {
throw new EntityNotFoundException(TemplateTestStep.class, name, Type.NAME);
}
TemplateTestStep givenTplTestStep = tplTestSteps.get(0);
ApplicationContext appContext = connectorService.getContextByName(sourceName);
TemplateTestStep newTplTestStep = copyTplTestStep(appContext.getEntityFactory().get(),
appContext.getEntityManager().get(), givenTplTestStep);
Set<Entity> entities = (Set<Entity>) DataAccessHelper.execute(getEntityManager(sourceName).get(),
Tuple.of(newTplTestStep, DataAccessHelper.CREATE));
return (T) entities.toArray()[0];
});
}
/**
* Create a copy of a given {@link TemplateTestStep} and set version to latest +
* 1
*
* @param entityFactory {@link EntityFactory} to create new
* {@link TemplateTestStep}
* @param entityManager {@link EntityManager} to get last version of given
* {@link TemplateTestStep}
* @param givenTplTestStep {@link TemplateTestStep} to create new version of
* @return copy of the given {@link TemplateTestStep}
*/
private TemplateTestStep copyTplTestStep(EntityFactory entityFactory, EntityManager entityManager,
TemplateTestStep givenTplTestStep) {
TemplateTestStep newTemplateTestStep = entityFactory.createTemplateTestStep(givenTplTestStep.getName());
Comparator<TemplateTestStep> versionComparator = Comparator.comparing(TemplateTestStep::getVersion);
Optional<Integer> latestVersion = entityManager.loadAll(TemplateTestStep.class, newTemplateTestStep.getName())
.stream().max(versionComparator).map(TemplateTestStep::getVersion);
if (latestVersion.isPresent()) {
newTemplateTestStep.setVersion(latestVersion.get() + 1);
}
for (TemplateRoot tplRoot : givenTplTestStep.getTemplateRoots()) {
newTemplateTestStep.setTemplateRoot(tplRoot);
}
return newTemplateTestStep;
}
/**
* * Create new version of {@link TemplateRoot} with given id
*
* @param sourceNameSupplier a {@link Value} with the source name (MDM
* {@link Environment} name)
* @param contextTypeSupplier a {@link Value} with the contextType of entity to
* create new version of.
* @param id id of entity to create new version of
* @return new version of the {@link TemplateRoot} with the given id
*/
@SuppressWarnings("unchecked")
public <T extends Entity> Try<T> createTplRootVersion(String sourceName, Value<ContextType> contextTypeSupplier,
String id) {
return Try.of(() -> {
TemplateRoot givenTplRoot = find(sourceName, TemplateRoot.class, id, contextTypeSupplier).get();
ApplicationContext appContext = connectorService.getContextByName(sourceName);
TemplateRoot newTplRoot = copyTplRoot(appContext.getEntityFactory().get(),
appContext.getEntityManager().get(), givenTplRoot);
Set<Entity> entities = (Set<Entity>) DataAccessHelper.execute(getEntityManager(sourceName).get(),
Tuple.of(newTplRoot, DataAccessHelper.CREATE));
return (T) entities.toArray()[0];
});
}
/**
* Create a copy of a given {@link TemplateRoot} and set version to latest + 1
*
* @param entityFactory {@link EntityFactory} to create new {@link TemplateRoot}
* @param entityManager {@link EntityManager} to get last version of given
* {@link TemplateRoot}
* @param givenTplRoot {@link TemplateRoot} to create new version of
* @return
*/
private TemplateRoot copyTplRoot(EntityFactory entityFactory, EntityManager entityManager,
TemplateRoot givenTplRoot) {
TemplateRoot newTemplateRoot = entityFactory.createTemplateRoot(givenTplRoot.getContextType(),
givenTplRoot.getName());
mergeEntities(givenTplRoot, newTemplateRoot, Entity.ATTR_NAME, Entity.ATTR_MIMETYPE,
TemplateRoot.ATTR_DATE_CREATED, TemplateRoot.ATTR_VERSION_STATE, TemplateRoot.ATTR_VERSION);
// TODO pschweinbenzidf on 2019-03-21: Why is this not working correctly with
// Versionable.COMPARATOR?
Comparator<TemplateRoot> versionComparator = Comparator.comparing(TemplateRoot::getVersion);
Optional<Integer> latestVersion = entityManager
.loadAll(TemplateRoot.class, givenTplRoot.getContextType(), newTemplateRoot.getName()).stream()
.max(versionComparator).map(TemplateRoot::getVersion);
if (latestVersion.isPresent()) {
newTemplateRoot.setVersion(latestVersion.get() + 1);
}
for (TemplateComponent tplComp : givenTplRoot.getTemplateComponents()) {
TemplateComponent newTplComp = entityFactory.createTemplateComponent(tplComp.getName(), newTemplateRoot,
tplComp.getCatalogComponent());
mergeEntities(tplComp, newTplComp, Entity.ATTR_NAME, Entity.ATTR_MIMETYPE);
copyTplAttrs(entityFactory, newTplComp, tplComp.getTemplateAttributes());
copyChildComps(entityFactory, newTplComp, tplComp.getTemplateComponents());
copyTplSensors(entityFactory, newTplComp, tplComp.getTemplateSensors());
}
return newTemplateRoot;
}
/**
* Copy given child {@link TemplateComponent}s into given
* {@link TemplateComponent}
*
* @param entityFactory {@link EntityFactory} to create new entities
* @param tplComp {@link TemplateComponent} into given child
* {@link TemplateComponent}s shall be copied
* @param givenChildComps {@link TemplateComponent}s which shall be copied
*/
private void copyChildComps(EntityFactory entityFactory, TemplateComponent tplComp,
List<TemplateComponent> givenChildComps) {
for (TemplateComponent childComp : givenChildComps) {
TemplateComponent newTplComp = tplComp.getTemplateComponents().stream()
.filter(tc -> tc.getName().equals(childComp.getName())).findFirst().orElseGet(() -> entityFactory
.createTemplateComponent(childComp.getName(), tplComp, childComp.getCatalogComponent()));
mergeEntities(childComp, newTplComp, Entity.ATTR_NAME, Entity.ATTR_MIMETYPE);
copyTplAttrs(entityFactory, newTplComp, childComp.getTemplateAttributes());
copyChildComps(entityFactory, newTplComp, childComp.getTemplateComponents());
copyTplSensors(entityFactory, newTplComp, childComp.getTemplateSensors());
}
}
/**
* Copy given {@link TemplateAttribute}s into given {@link TemplateComponent}
*
* @param entityFactory {@link EntityFactory} to create new entities
* @param tplComp {@link TemplateComponent} into given
* {@link TemplateAttribute}s shall be copied
* @param givenTplAttrs {@link TemplateAttribute}s which shall be copied
*/
private void copyTplAttrs(EntityFactory entityFactory, TemplateComponent tplComp,
List<TemplateAttribute> givenTplAttrs) {
for (TemplateAttribute tplAttr : givenTplAttrs) {
TemplateAttribute newTplAttr = tplComp.getTemplateAttributes().stream()
.filter(ta -> ta.getName().equals(tplAttr.getName())).findFirst()
.orElseGet(() -> entityFactory.createTemplateAttribute(tplAttr.getName(), tplComp));
mergeEntities(tplAttr, newTplAttr, Entity.ATTR_NAME, Entity.ATTR_MIMETYPE);
}
}
/**
* Copy given {@link TemplateSeonsor}s into given {@link TemplateComponent}
*
* @param entityFactory {@link EntityFactory} to create new entities
* @param tplComp {@link TemplateComponent} into given
* {@link TemplateSensor}s shall be copied
* @param givenTplSensors {@link TemplateSensor}s which shall be copied
*/
private void copyTplSensors(EntityFactory entityFactory, TemplateComponent tplComp,
List<TemplateSensor> givenTplSensors) {
for (TemplateSensor tplSensor : givenTplSensors) {
TemplateSensor newTplSensor = tplComp.getTemplateSensors().stream()
.filter(ts -> ts.getName().equals(tplSensor.getName())).findFirst()
.orElseGet(() -> entityFactory.createTemplateSensor(tplSensor.getName(), tplComp,
tplSensor.getCatalogSensor(), tplSensor.getQuantity()));
mergeEntities(tplSensor, newTplSensor, Entity.ATTR_NAME, Entity.ATTR_MIMETYPE);
for (TemplateAttribute tplSensorAttr : tplSensor.getTemplateAttributes()) {
Optional<TemplateAttribute> newTplSensorAttr = newTplSensor.getTemplateAttributes().stream()
.filter(ta -> ta.getName().equals(tplSensorAttr.getName())).findFirst();
if (newTplSensorAttr.isPresent()) {
mergeEntities(tplSensorAttr, newTplSensorAttr.get(), Entity.ATTR_NAME, Entity.ATTR_MIMETYPE);
}
}
}
}
/**
* Merge given {@link Entity}s
*
* @param entity original {@link Entity} which shall be merged into given
* updEntity
* @param updEntity {@link Entity} which shall be updated by given entity
* @param ignoredAttrs optional attributes which are not merged
*/
private void mergeEntities(Entity entity, Entity updEntity, String... ignoredAttrs) {
if (!entity.getClass().isAssignableFrom(updEntity.getClass())) {
return;
}
Set<String> ingoredAttrs = new HashSet<>(Arrays.asList(ignoredAttrs));
Map<String, org.eclipse.mdm.api.base.model.Value> entityValues = entity.getValues();
Set<String> updEntityKeys = updEntity.getValues().keySet();
for (Map.Entry<String, org.eclipse.mdm.api.base.model.Value> entry : entityValues.entrySet()) {
String key = entry.getKey();
if (!ingoredAttrs.contains(key) && updEntityKeys.contains(key)) {
updEntity.getValue(entry.getKey()).set(entry.getValue().extract());
}
}
}
}