| /******************************************************************************** |
| * 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()); |
| } |
| } |
| } |
| |
| } |