blob: d06c762ce6958cd80a1cc21965facdccbc33969d [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 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)
*
*/
@Stateless
public class TemplateRootService extends EntityService {
/**
* 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
*/
@SuppressWarnings("unchecked")
public <T extends Entity> Try<T> createNewVersion(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 = createNewTplRootVersion(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 new version of given {@link TemplateRoot}
*
* @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 createNewTplRootVersion(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 {@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 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 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());
}
}
}
}