| /******************************************************************************** |
| * Copyright (c) 2015-2020 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.apicopy.control; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Optional; |
| import java.util.Set; |
| import java.util.stream.Collectors; |
| |
| import org.eclipse.mdm.api.base.Transaction; |
| import org.eclipse.mdm.api.base.adapter.EntityType; |
| import org.eclipse.mdm.api.base.adapter.Relation; |
| import org.eclipse.mdm.api.base.massdata.ReadRequest; |
| import org.eclipse.mdm.api.base.massdata.ReadRequest.ValuesMode; |
| import org.eclipse.mdm.api.base.massdata.WriteRequest; |
| import org.eclipse.mdm.api.base.model.Channel; |
| import org.eclipse.mdm.api.base.model.ChannelGroup; |
| import org.eclipse.mdm.api.base.model.ContextComponent; |
| import org.eclipse.mdm.api.base.model.ContextRoot; |
| import org.eclipse.mdm.api.base.model.ContextType; |
| import org.eclipse.mdm.api.base.model.Entity; |
| import org.eclipse.mdm.api.base.model.MeasuredValues; |
| import org.eclipse.mdm.api.base.model.Measurement; |
| import org.eclipse.mdm.api.base.model.Quantity; |
| import org.eclipse.mdm.api.base.model.Test; |
| import org.eclipse.mdm.api.base.model.TestStep; |
| import org.eclipse.mdm.api.base.model.Unit; |
| import org.eclipse.mdm.api.base.model.User; |
| import org.eclipse.mdm.api.base.model.Value; |
| import org.eclipse.mdm.api.base.model.VersionState; |
| import org.eclipse.mdm.api.dflt.ApplicationContext; |
| import org.eclipse.mdm.api.dflt.EntityManager; |
| import org.eclipse.mdm.api.dflt.model.Classification; |
| import org.eclipse.mdm.api.dflt.model.Pool; |
| import org.eclipse.mdm.api.dflt.model.Project; |
| import org.eclipse.mdm.api.dflt.model.TemplateComponent; |
| import org.eclipse.mdm.api.dflt.model.TemplateRoot; |
| import org.eclipse.mdm.api.dflt.model.TemplateTest; |
| import org.eclipse.mdm.api.dflt.model.TemplateTestStep; |
| import org.eclipse.mdm.api.dflt.model.Versionable; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import com.google.common.base.Strings; |
| import com.google.common.collect.ListMultimap; |
| |
| public class ImportTask extends TransferBase implements ApiCopyTask { |
| |
| /** |
| * Property to configure to overwrite the existing test step |
| * |
| * Default: false |
| * |
| * If true and the matching target test step exists, context data will be |
| * overwritten and the measurements will be imported as children of the existing |
| * teststep. |
| * |
| * Otherwise a new test step will be created |
| */ |
| private static final String PROPERTY_OVERWRITE_EXISTING_ELEMENTS = "overwriteExistingElements"; |
| private static final String DEFAULT_OVERWRITE_EXISTING_ELEMENTS = "false"; |
| |
| /** |
| * Property to configure that existing measured values will be appended |
| * |
| * Default: false |
| * |
| * If true the measured value of the import data set will be appended to the |
| * existing. That means, if the target measurement already exists the importer |
| * will add the measured values of the source column to the target column. If at |
| * the the target measurement the column not exists, the importer create a new |
| * one, add first invalid values with the count of the target submatrix size, |
| * and add there the source values. |
| * |
| * If false and the target measurement already exists, the import task will be |
| * canceled |
| */ |
| private static final String PROPERTY_APPEND = "append"; |
| private static final String DEFAULT_APPEND = "false"; |
| |
| /** |
| * Property to configure that existing file links will be replaced |
| * |
| * Default: false |
| * |
| * If true, file links of the target entities will be replaced, if in the source |
| * the file link exists |
| * |
| * Otherwise new file links will be added to the existing sequence. |
| */ |
| private static final String PROPERTY_REPLACE_FILELINKS = "replaceFileLinks"; |
| private static final String DEFAULT_REPLACE_FILES = "false"; |
| |
| private static final Logger LOG = LoggerFactory.getLogger(ImportTask.class); |
| |
| private ClassificationUtil classificationUtil; |
| private TemplateManager templateManager; |
| |
| private Map<String, String> quantityMapping = new HashMap<>(); |
| |
| private Map<String, String> unitMapping = new HashMap<>(); |
| |
| private Map<String, String> properties = new HashMap<>(); |
| |
| private boolean replaceFileLinks = false; |
| |
| public ImportTask(ApplicationContext src, ApplicationContext dst, TemplateManager templateManager) { |
| super(src, dst); |
| |
| if (templateManager == null) { |
| this.templateManager = new DefaultTemplateManager(); |
| } else { |
| this.templateManager = templateManager; |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.mdm.apicopy.control.ApiCopyTask#setUnitMapping(java.util.Map) |
| */ |
| @Override |
| public void setUnitMapping(Map<String, String> unitMapping) { |
| this.unitMapping = unitMapping; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.mdm.apicopy.control.ApiCopyTask#setQuantityMapping(java.util.Map) |
| */ |
| @Override |
| public void setQuantityMapping(Map<String, String> quantityMapping) { |
| this.quantityMapping = quantityMapping; |
| } |
| |
| @Override |
| public void copy(List<? extends Entity> entities) { |
| Transaction transaction = entityManagerDst.startTransaction(); |
| classificationUtil = new ClassificationUtil(transaction, contextDst); |
| try { |
| mapSrcDstEntities.clear(); |
| |
| ListMultimap<Class<? extends Entity>, Entity> parents = loadParents(entities); |
| LOG.trace("Resolved parents: {}", parents); |
| supportedRootEntities.forEach(ec -> parents.get(ec).forEach(e -> copyEntity(e, false, transaction))); |
| |
| LOG.trace("Import entities: {}", entities); |
| entities.forEach(e -> copyEntity(e, true, transaction)); |
| transaction.commit(); |
| deleteFilesOfReplacedFileLinks(); |
| } catch (Exception exc) { |
| try { |
| transaction.abort(); |
| } catch (Exception exc2) { |
| LOG.error("Could not abort transaction!"); |
| } |
| deleteFilesOfUploadedFileLinks(); |
| |
| throw new ApiCopyException("Could not copy data: " + exc.getMessage(), exc); |
| } finally { |
| classificationUtil.clearCache(); |
| clearReplacedFileLinkCache(); |
| clearUploadedFileLinkCache(); |
| deleteLocalTempFiles(); |
| } |
| } |
| |
| @Override |
| public boolean isReplaceFileLinks() { |
| return replaceFileLinks; |
| } |
| |
| private Entity copyEntity(Entity entity, boolean recursive, Transaction transaction) { |
| if (entity instanceof Project) { |
| return copyProject((Project) entity, recursive, transaction); |
| } else if (entity instanceof Pool) { |
| return copyPool((Pool) entity, recursive, transaction); |
| } else if (entity instanceof Test) { |
| return copyTest((Test) entity, recursive, transaction); |
| } else if (entity instanceof TestStep) { |
| return copyTestStep((TestStep) entity, recursive, transaction); |
| } else if (entity instanceof Measurement) { |
| return copyMeasurement((Measurement) entity, new ArrayList<ContextRoot>(), recursive, transaction); |
| } else { |
| throw new ApiCopyException("Unsupported entity: '" + entity.getClass().getName() + "'"); |
| } |
| } |
| |
| private Project copyProject(Project projectSrc, boolean recursive, Transaction transaction) { |
| EntityHolder ehSrc = new EntityHolder(projectSrc, entityManagerSrc); |
| |
| EntityHolder ehDst = mapSrcDstEntities.get(ehSrc); |
| |
| if (null == ehDst) { |
| |
| Optional<Project> projectOpt = fetchOne(entityManagerDst, Project.class, projectSrc.getName()); |
| |
| if (projectOpt.isPresent()) { |
| LOG.trace("Project '{}' already exists.", projectSrc.getName()); |
| ehDst = new EntityHolder(projectOpt.get(), entityManagerDst); |
| } else { |
| LOG.trace("Importing Project '{}'.", projectSrc.getName()); |
| |
| Project projectDst = entityFactoryDst.createProject(projectSrc.getName()); |
| copyValues(projectSrc, projectDst, Arrays.asList("Id", "Name"), false); |
| |
| persist(transaction, projectDst); |
| ehDst = new EntityHolder(projectDst, entityManagerDst); |
| } |
| |
| mapSrcDstEntities.put(ehSrc, ehDst); |
| |
| if (recursive) { |
| entityManagerSrc.loadChildren(projectSrc, Pool.class) |
| .forEach(pool -> copyPool(pool, recursive, transaction)); |
| } |
| } |
| |
| return (Project) ehDst.getEntity(); |
| } |
| |
| private Pool copyPool(Pool poolSrc, boolean recursive, Transaction transaction) { |
| EntityHolder ehSrc = new EntityHolder(poolSrc, entityManagerSrc); |
| |
| EntityHolder ehDst = mapSrcDstEntities.get(ehSrc); |
| |
| if (null == ehDst) { |
| LOG.trace("Importing Pool '{}'", poolSrc.getName()); |
| |
| Project projectParentDst = (Project) mapSrcDstEntities |
| .get(new EntityHolder(entityManagerSrc.loadParent(poolSrc, Project.class).get(), entityManagerSrc)) |
| .getEntity(); |
| |
| Optional<Pool> poolOpt = fetchChild(entityManagerDst, projectParentDst, Pool.class, poolSrc.getName()); |
| |
| if (poolOpt.isPresent()) { |
| LOG.trace("Pool '{}' already exists.", poolSrc.getName()); |
| ehDst = new EntityHolder(poolOpt.get(), entityManagerDst); |
| } else { |
| LOG.trace("Importing Pool '{}'.", poolSrc.getName()); |
| |
| Pool poolDst = entityFactoryDst.createPool(poolSrc.getName(), projectParentDst); |
| copyValues(poolSrc, poolDst, Arrays.asList("Id", "Name"), false); |
| |
| persist(transaction, poolDst); |
| ehDst = new EntityHolder(poolDst, entityManagerDst); |
| } |
| |
| mapSrcDstEntities.put(ehSrc, ehDst); |
| |
| if (recursive) { |
| entityManagerSrc.loadChildren(poolSrc, Test.class) |
| .forEach(test -> copyTest(test, recursive, transaction)); |
| } |
| } |
| |
| return (Pool) ehDst.getEntity(); |
| } |
| |
| private Test copyTest(Test testSrc, boolean recursive, Transaction transaction) { |
| EntityHolder ehSrc = new EntityHolder(testSrc, entityManagerSrc); |
| |
| EntityHolder ehDst = mapSrcDstEntities.get(ehSrc); |
| |
| if (null == ehDst) { |
| |
| Pool poolParentDst = (Pool) mapSrcDstEntities |
| .get(new EntityHolder(entityManagerSrc.loadParent(testSrc, Pool.class).get(), entityManagerSrc)) |
| .getEntity(); |
| |
| Optional<TemplateTest> templateTestDst = loadTemplateTest(testSrc); |
| |
| String rootProjectName = getProjectName(testSrc, entityManagerSrc); |
| |
| Optional<Test> testOpt = fetchChild(entityManagerDst, poolParentDst, Test.class, testSrc.getName()); |
| |
| if (testOpt.isPresent()) { |
| LOG.trace("Test '{}' already exists.", testSrc.getName()); |
| ehDst = new EntityHolder(testOpt.get(), entityManagerDst); |
| } else { |
| Test testDst; |
| if (templateTestDst.isPresent()) { |
| LOG.trace("Importing Test '{}' using TestTemplate '{}'", testSrc.getName(), |
| templateTestDst.get().getName()); |
| testDst = entityFactoryDst.createTest(testSrc.getName(), poolParentDst, templateTestDst.get(), |
| classificationUtil.getClassification(rootProjectName), false); |
| } else { |
| LOG.trace("Importing Test '{}' using no TestTemplate", testSrc.getName()); |
| testDst = entityFactoryDst.createTest(testSrc.getName(), poolParentDst, null, |
| classificationUtil.getClassification(rootProjectName), false); |
| } |
| |
| copyValues(testSrc, testDst, Arrays.asList("Id", "Name"), true); |
| |
| // copy responsible person: |
| Optional<User> userSrc = testSrc.getResponsiblePerson(); |
| if (userSrc.isPresent()) { |
| User userDst = entityManagerDst.loadAll(User.class, userSrc.get().getName()).stream().findFirst() |
| .orElseThrow(() -> new ApiCopyException(String.format( |
| "No User instance with name %s found in destination!", userSrc.get().getName()))); |
| |
| testDst.setResponsiblePerson(userDst); |
| } |
| |
| persist(transaction, testDst); |
| |
| ehDst = new EntityHolder(testDst, entityManagerDst); |
| } |
| |
| mapSrcDstEntities.put(ehSrc, ehDst); |
| |
| if (recursive) { |
| EntityType etTestStep = modelManagerDst.getEntityType(TestStep.class); |
| EntityType etTest = modelManagerDst.getEntityType(Test.class); |
| |
| Relation relTest = etTestStep.getRelation(etTest); |
| |
| if (null == relTest) { |
| throw new ApiCopyException("No relation to Test found at TestStep!"); |
| } |
| |
| copyTestSteps(testSrc, recursive, templateTestDst, (Test) ehDst.getEntity(), transaction); |
| entityManagerSrc.loadChildren(testSrc, TestStep.class) |
| .forEach(testStep -> copyTestStep(testStep, recursive, transaction)); |
| } |
| } |
| |
| return (Test) ehDst.getEntity(); |
| } |
| |
| private TestStep copyTestStep(TestStep testStepSrc, boolean recursive, Transaction transaction) { |
| EntityHolder ehSrc = new EntityHolder(testStepSrc, entityManagerSrc); |
| |
| EntityHolder ehDst = mapSrcDstEntities.get(ehSrc); |
| |
| if (null == ehDst) { |
| LOG.trace("Importing TestStep '{}'", testStepSrc.getName()); |
| |
| Test testDst = (Test) mapSrcDstEntities |
| .get(new EntityHolder(entityManagerSrc.loadParent(testStepSrc, Test.class).get(), entityManagerSrc)) |
| .getEntity(); |
| |
| Optional<TemplateTestStep> templateTestStep = loadTemplateTestStep(testStepSrc); |
| |
| String rootProjectName = getProjectName(testStepSrc, entityManagerSrc); |
| |
| TestStep testStepDst = fetchChild(entityManagerDst, testDst, TestStep.class, testStepSrc.getName()) |
| .orElseGet(() -> { |
| if (templateTestStep.isPresent() && hasContextData(testStepSrc)) { |
| LOG.trace("Importing TestStep '{}' using TestStepTemplate '{}' and create context roots", |
| testStepSrc.getName(), templateTestStep.get().getName()); |
| return entityFactoryDst.createTestStep(testDst, templateTestStep.get(), |
| classificationUtil.getClassification(rootProjectName)); |
| } else if (templateTestStep.isPresent()) { |
| LOG.trace("Importing TestStep '{}' using TestStepTemplate '{}'", testStepSrc.getName(), |
| templateTestStep.get().getName()); |
| return entityFactoryDst.createTestStepWithOutContextRoots(testDst, templateTestStep.get(), |
| classificationUtil.getClassification(rootProjectName)); |
| } else { |
| LOG.trace("Importing TestStep '{}' using no TestStepTemplate", testStepSrc.getName()); |
| TestStep createdTestStep = entityFactoryDst.createTestStep(testStepSrc.getName(), testDst, |
| classificationUtil.getClassification(rootProjectName)); |
| return createdTestStep; |
| } |
| }); |
| |
| copyValues(testStepSrc, testStepDst, Arrays.asList("Id"), true); |
| |
| persist(transaction, testStepDst); |
| |
| ehDst = new EntityHolder(testStepDst, entityManagerDst); |
| mapSrcDstEntities.put(ehSrc, ehDst); |
| |
| Map<ContextType, ContextRoot> mapContextRootsSrc = testStepSrc.loadContexts(entityManagerSrc, |
| ContextType.values()); |
| Map<ContextType, ContextRoot> mapContextRootsDst = testStepDst.loadContexts(entityManagerDst, |
| ContextType.values()); |
| |
| copyContext(mapContextRootsSrc, mapContextRootsDst, templateTestStep, transaction); |
| |
| if (recursive) { |
| List<ContextRoot> listContextRoots = new ArrayList<>(); |
| entityManagerSrc.loadChildren(testStepSrc, Measurement.class) |
| .forEach(measurement -> copyMeasurement(measurement, listContextRoots, recursive, transaction)); |
| } |
| } |
| return (TestStep) ehDst.getEntity(); |
| } |
| |
| private String getProjectName(TestStep testStep, EntityManager entityManager) { |
| Optional<Test> parentTest = entityManager.loadParent(testStep, Test.class); |
| |
| if (!parentTest.isPresent()) { |
| throw new ApiCopyException("Parent of source teststep not found!"); |
| } |
| |
| return getProjectName(parentTest.get(), entityManager); |
| } |
| |
| private String getProjectName(Test test, EntityManager entityManager) { |
| |
| Optional<Pool> parentPool = entityManager.loadParent(test, Pool.class); |
| |
| if (!parentPool.isPresent()) { |
| throw new ApiCopyException("Parent of source test not found!"); |
| } |
| |
| Optional<Project> parentProject = entityManager.loadParent(parentPool.get(), Project.class); |
| |
| if (!parentProject.isPresent()) { |
| throw new ApiCopyException("Parent of source pool not found!"); |
| } |
| |
| return parentProject.get().getName(); |
| } |
| |
| /** |
| * Check if the teststep has context data |
| * |
| * @param testStepSrc |
| * @return true if the teststep has conteyt data |
| */ |
| private boolean hasContextData(TestStep testStepSrc) { |
| boolean hasContextData = false; |
| |
| Optional<EntityManager> entityManager = contextSrc.getEntityManager(); |
| if (entityManager.isPresent()) { |
| Map<ContextType, ContextRoot> loadContexts = entityManager.get().loadContexts(testStepSrc, |
| ContextType.UNITUNDERTEST, ContextType.TESTEQUIPMENT, ContextType.TESTSEQUENCE); |
| if (!loadContexts.isEmpty()) { |
| hasContextData = true; |
| } |
| } |
| |
| return hasContextData; |
| |
| } |
| |
| private List<TestStep> copyTestSteps(Test testSrc, boolean recursive, Optional<TemplateTest> templateTestDst, |
| Test testDst, Transaction transaction) { |
| |
| List<TestStep> listTestStepsSrc = entityManagerSrc.loadChildren(testSrc, TestStep.class); |
| |
| List<TestStep> listTestStepsDst = new ArrayList<>(); |
| for (int i = 0, len = listTestStepsSrc.size(); i < len; ++i) { |
| TestStep testStepSrc = listTestStepsSrc.get(i); |
| Optional<TemplateTestStep> templateTestStep = loadTemplateTestStep(testStepSrc); |
| |
| String rootProjectName = getProjectName(testStepSrc, entityManagerSrc); |
| |
| Optional<TestStep> oTestSTepDst = fetchChild(entityManagerDst, testDst, TestStep.class, |
| testStepSrc.getName()); |
| |
| TestStep testStepDst; |
| |
| boolean overwriteExistingElements = Boolean.valueOf( |
| properties.getOrDefault(PROPERTY_OVERWRITE_EXISTING_ELEMENTS, DEFAULT_OVERWRITE_EXISTING_ELEMENTS)); |
| |
| if (!overwriteExistingElements || (overwriteExistingElements && !oTestSTepDst.isPresent())) { |
| if (templateTestStep.isPresent() && hasContextData(testStepSrc)) { |
| LOG.trace("Importing TestStep '{}' using TestStepTemplate '{}' and create context roots", |
| testStepSrc.getName(), templateTestStep.get().getName()); |
| testStepDst = entityFactoryDst.createTestStep(testDst, templateTestStep.get(), |
| classificationUtil.getClassification(rootProjectName)); |
| testStepDst.setName(testStepSrc.getName()); |
| } else if (templateTestStep.isPresent()) { |
| LOG.trace("Importing TestStep '{}' using TestStepTemplate '{}' and create context roots", |
| testStepSrc.getName(), templateTestStep.get().getName()); |
| testStepDst = entityFactoryDst.createTestStepWithOutContextRoots(testDst, templateTestStep.get(), |
| classificationUtil.getClassification(rootProjectName)); |
| } else { |
| LOG.trace("Importing TestStep '{}' using no TestStepTemplate", testStepSrc.getName()); |
| testStepDst = entityFactoryDst.createTestStep(testStepSrc.getName(), testDst, |
| classificationUtil.getClassification(rootProjectName)); |
| } |
| } else { |
| testStepDst = oTestSTepDst.get(); |
| } |
| |
| copyValues(testStepSrc, testStepDst, Arrays.asList("Id"), true); |
| |
| listTestStepsDst.add(testStepDst); |
| |
| mapSrcDstEntities.put(new EntityHolder(testStepSrc, entityManagerSrc), |
| new EntityHolder(testStepDst, entityManagerDst)); |
| } |
| |
| for (TestStep testStepSrc : listTestStepsSrc) { |
| Optional<TestStep> testStepDst = listTestStepsDst.stream() |
| .filter(n -> n.getName().equals(testStepSrc.getName())).findFirst(); |
| |
| if (testStepDst.isPresent()) { |
| Map<ContextType, ContextRoot> mapContextRootsSrc = testStepSrc.loadContexts(entityManagerSrc, |
| ContextType.values()); |
| Map<ContextType, ContextRoot> mapContextRootsDst = testStepDst.get().loadContexts(entityManagerDst, |
| ContextType.values()); |
| copyContext(mapContextRootsSrc, mapContextRootsDst, loadTemplateTestStep(testStepSrc), transaction); |
| } |
| } |
| |
| persist(transaction, listTestStepsDst); |
| |
| if (recursive) { |
| for (TestStep testStep : listTestStepsSrc) { |
| List<ContextRoot> listContextRoots = new ArrayList<>(); |
| entityManagerSrc.loadChildren(testStep, Measurement.class) |
| .forEach(measurement -> copyMeasurement(measurement, listContextRoots, recursive, transaction)); |
| } |
| } |
| |
| return listTestStepsDst; |
| } |
| |
| private void copyContext(Map<ContextType, ContextRoot> mapContextRootsSrc, |
| Map<ContextType, ContextRoot> mapContextRootsDst, Optional<TemplateTestStep> optTemplateTestStep, |
| Transaction transaction) { |
| |
| for (Map.Entry<ContextType, ContextRoot> me : mapContextRootsSrc.entrySet()) { |
| LOG.trace("Importing ContextRoot '{}'", me.getKey()); |
| ContextRoot contextRootDst = mapContextRootsDst.get(me.getKey()); |
| if (null != contextRootDst && contextRootDst.getName().equals(me.getValue().getName())) { |
| ContextRoot contextRootSrc = me.getValue(); |
| copyValues(contextRootSrc, contextRootDst, Arrays.asList("Id", "Name"), false); |
| |
| TemplateRoot templateRootDst = null; |
| |
| if (optTemplateTestStep.isPresent()) { |
| Optional<TemplateRoot> optTemplateRoot = optTemplateTestStep.get() |
| .getTemplateRoot(contextRootDst.getContextType()); |
| |
| templateRootDst = optTemplateRoot.orElse(null); |
| } |
| |
| for (ContextComponent contextComponentSrc : me.getValue().getContextComponents()) { |
| LOG.trace("Importing ContextComponent '{}'", contextComponentSrc.getName()); |
| Optional<ContextComponent> o = contextRootDst.getContextComponent(contextComponentSrc.getName()); |
| |
| if (o.isPresent()) { |
| ContextComponent contextComponentDst = o.get(); |
| |
| copyValues(contextComponentSrc, contextComponentDst, Arrays.asList("Id", "Name"), true); |
| |
| } else if (null != templateRootDst) { |
| Optional<TemplateComponent> optTemplateComponent = templateRootDst |
| .getTemplateComponent(contextComponentSrc.getName()); |
| |
| if (optTemplateComponent.isPresent()) { |
| TemplateComponent templateComponent = optTemplateComponent.get(); |
| if (templateComponent.isOptional() && !templateComponent.isDefaultActive()) { |
| ContextComponent contextComponentDst = entityFactoryDst |
| .createContextComponent(contextComponentSrc.getName(), contextRootDst); |
| |
| copyValues(contextComponentSrc, contextComponentDst, Arrays.asList("Id", "Name"), true); |
| |
| persist(transaction, contextComponentDst); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| private Measurement copyMeasurement(Measurement measurementSrc, List<ContextRoot> listContextRootsDst, |
| boolean recursive, Transaction transaction) { |
| EntityHolder ehSrc = new EntityHolder(measurementSrc, entityManagerSrc); |
| |
| EntityHolder ehDst = mapSrcDstEntities.get(ehSrc); |
| |
| boolean append = Boolean.valueOf(properties.getOrDefault(PROPERTY_APPEND, DEFAULT_APPEND)); |
| |
| if (null == ehDst) { |
| LOG.trace("Importing Measurement '{}'", measurementSrc.getName()); |
| TestStep testStepSrs = entityManagerSrc.loadParent(measurementSrc, TestStep.class).get(); |
| TestStep testStepParentDst = (TestStep) mapSrcDstEntities |
| .get(new EntityHolder(testStepSrs, entityManagerSrc)).getEntity(); |
| |
| // EntityType etMeasurement = modelManagerDst.getEntityType(Measurement.class); |
| // EntityType etTestStep = modelManagerDst.getEntityType(TestStep.class); |
| // |
| // Relation relTestStep = etMeasurement.getRelation(etTestStep); |
| // |
| // if (null == relTestStep) { |
| // throw new ApiCopyException("No relation to TestStep found at MeaResult!"); |
| // } |
| // |
| // Filter filter = Filter.nameOnly(etMeasurement, measurementSrc.getName()).id(relTestStep, |
| // testStepParentDst.getID()); |
| // |
| // Optional<Measurement> optMeasurement = fetchOne(searchServiceDst, Measurement.class, filter); |
| Optional<Measurement> optMeasurement = fetchChild(entityManagerDst, testStepParentDst, Measurement.class, |
| measurementSrc.getName()); |
| |
| Measurement measurementDst = null; |
| |
| if (optMeasurement.isPresent() && !append) { |
| throw new ApiCopyException(String.format("TestStep '%s' has already a measurement with name '%s'!", |
| testStepParentDst.getName(), measurementSrc.getName())); |
| } else if (optMeasurement.isPresent()) { |
| measurementDst = optMeasurement.get(); |
| } else { |
| append = false; |
| } |
| |
| Optional<TemplateTestStep> optTemplateTestStep = loadTemplateTestStep(testStepSrs); |
| |
| // If no ContextRoots to use with the newly created Measurement are passed into |
| // this method, use ContextRoots |
| // of any already existing Measurement under the parent test step. |
| // First look in destination... |
| if (listContextRootsDst.isEmpty()) { |
| for (Measurement existingMeasurementDst : entityManagerDst.loadChildren(testStepParentDst, |
| Measurement.class)) { |
| listContextRootsDst.addAll( |
| existingMeasurementDst.loadContexts(entityManagerDst, ContextType.values()).values()); |
| |
| if (!listContextRootsDst.isEmpty()) { |
| break; |
| } |
| } |
| } |
| |
| // ...then, if nothing has been found, in source and try to find destination |
| // counterpart in cache map: |
| if (listContextRootsDst.isEmpty()) { |
| for (Measurement existingMeasurementSrc : entityManagerSrc.loadChildren(testStepSrs, |
| Measurement.class)) { |
| EntityHolder eh = mapSrcDstEntities.get(new EntityHolder(existingMeasurementSrc, entityManagerSrc)); |
| if (null != eh) { |
| listContextRootsDst.addAll(((Measurement) eh.getEntity()) |
| .loadContexts(entityManagerDst, ContextType.values()).values()); |
| } |
| |
| if (!listContextRootsDst.isEmpty()) { |
| break; |
| } |
| } |
| } |
| |
| // Still no ContextRoots found? Create them from the test step template: |
| if (listContextRootsDst.isEmpty() && optTemplateTestStep.isPresent()) { |
| optTemplateTestStep.get().getTemplateRoots() |
| .forEach(tr -> listContextRootsDst.add(entityFactoryDst.createContextRoot(tr))); |
| } |
| |
| if (measurementDst == null) { |
| measurementDst = entityFactoryDst.createMeasurement(measurementSrc.getName(), testStepParentDst, |
| listContextRootsDst.toArray(new ContextRoot[listContextRootsDst.size()])); |
| } |
| |
| copyValues(measurementSrc, measurementDst, Arrays.asList("Id", "Name"), true); |
| |
| ehDst = new EntityHolder(measurementDst, entityManagerDst); |
| mapSrcDstEntities.put(ehSrc, ehDst); |
| |
| Map<ContextType, ContextRoot> mapContextRootsSrc = testStepParentDst.loadContexts(entityManagerDst, |
| ContextType.values()); |
| Map<ContextType, ContextRoot> mapContextRootsDst = measurementDst.loadContexts(entityManagerDst, |
| ContextType.values()); |
| |
| copyContext(mapContextRootsSrc, mapContextRootsDst, optTemplateTestStep, transaction); |
| |
| mapContextRootsSrc = measurementSrc.loadContexts(entityManagerSrc, ContextType.values()); |
| mapContextRootsDst = measurementDst.loadContexts(entityManagerDst, ContextType.values()); |
| copyContext(mapContextRootsSrc, mapContextRootsDst, optTemplateTestStep, transaction); |
| |
| persist(transaction, measurementDst); |
| |
| String projectName = getProjectName(entityManagerSrc.loadParent(measurementSrc, TestStep.class).get(), |
| entityManagerSrc); |
| Classification classification = classificationUtil.getClassification(projectName); |
| classification.assign(testStepParentDst); |
| persist(transaction, testStepParentDst); |
| |
| Iterator<ContextRoot> contextRootIter = mapContextRootsDst.values().iterator(); |
| |
| while (contextRootIter.hasNext()) { |
| ContextRoot contextRootForUpdate = contextRootIter.next(); |
| persist(transaction, contextRootForUpdate); |
| } |
| |
| if (recursive) { |
| List<Channel> sourceChannels = entityManagerSrc.loadChildren(measurementSrc, Channel.class); |
| List<WriteRequest> listWriteRequests = new ArrayList<>(); |
| |
| Map<String, Channel> mapChannelsDst = new HashMap<>(); |
| Map<String, Channel> mapChannelsSrc = new HashMap<>(); |
| |
| List<Channel> existingChannels = entityManagerDst.loadChildren(measurementDst, Channel.class); |
| if (append && !isSrcChannelsValid(sourceChannels, existingChannels)) { |
| throw new ApiCopyException( |
| "Appending not possible. All channels of existing measurement have to be in the source measurement"); |
| } |
| |
| Map<String, Optional<Quantity>> quantitiesByName = preloadQuantities(sourceChannels); |
| for (Channel channel : sourceChannels) { |
| Channel channelDst = copyChannel(channel, measurementDst, existingChannels, quantitiesByName, |
| transaction); |
| mapChannelsDst.put(channel.getName(), channelDst); |
| mapChannelsSrc.put(channel.getName(), channel); |
| } |
| |
| for (ChannelGroup channelGroupSrc : entityManagerSrc.loadChildren(measurementSrc, ChannelGroup.class)) { |
| Map<String, MeasuredValues> existingMeasValuesToAppend = new HashMap<>(); |
| |
| Integer numberOfValues = 0; |
| if (append) { |
| Optional<ChannelGroup> optChannelGroup = fetchOneChannelGroup(entityManagerSrc, |
| channelGroupSrc); |
| |
| if (optChannelGroup.isPresent()) { |
| numberOfValues = optChannelGroup.get().getNumberOfValues(); |
| existingMeasValuesToAppend = getMeasurementValuesMap(entityManagerDst, |
| optChannelGroup.get()); |
| } |
| |
| } |
| |
| ChannelGroup channelGroupDst = copyChannelGroup(channelGroupSrc, transaction, append); |
| |
| for (MeasuredValues measuredValues : entityManagerSrc.readMeasuredValues(ReadRequest |
| .create(channelGroupSrc).valuesMode(ValuesMode.STORAGE).allChannels().allValues())) { |
| LOG.trace("Importing MeasuredValues '{}'", measuredValues.getName()); |
| if (!mapChannelsDst.containsKey(measuredValues.getName())) { |
| throw new ApiCopyException( |
| String.format("Cannot find Channel %s in destination!", measuredValues.getName())); |
| } |
| |
| Channel channelDst = mapChannelsDst.get(measuredValues.getName()); |
| |
| String sourceUnitName = unitMapping.getOrDefault(measuredValues.getUnit(), |
| measuredValues.getUnit()); |
| |
| List<Unit> sourceUnits = entityManagerDst.loadAll(Unit.class, sourceUnitName); |
| |
| if (sourceUnits == null || sourceUnits.isEmpty()) { |
| throw new ApiCopyException( |
| String.format("Unit with name '%s' not found in target!", sourceUnitName)); |
| } |
| |
| if (append) { |
| |
| Channel channelSrc = mapChannelsSrc.get(channelDst.getName()); |
| channelDst = replaceChannelDst(channelSrc, channelDst, measurementDst, ehSrc, transaction); |
| |
| MeasuredValues measuredValuesOld = existingMeasValuesToAppend.get(channelDst.getName()); |
| |
| if (measuredValuesOld == null) { |
| measuredValuesOld = MeasuredValuesHelper.createEmptyValues(measuredValues.getName(), |
| measuredValues.getScalarType(), measuredValues.getUnit(), |
| measuredValues.getSequenceRepresentation(), |
| measuredValues.getGenerationParameters(), measuredValues.isIndependent(), |
| measuredValues.getAxisType(), numberOfValues); |
| } |
| |
| measuredValues = MeasuredValuesHelper.appenMeasuredValues(measuredValuesOld, |
| measuredValues); |
| |
| } |
| |
| listWriteRequests.add( |
| createWriteRequest(channelGroupDst, channelDst, measuredValues, sourceUnits.get(0))); |
| } |
| } |
| |
| transaction.writeMeasuredValues(listWriteRequests); |
| } |
| } |
| |
| return (Measurement) ehDst.getEntity(); |
| } |
| |
| private boolean isSrcChannelsValid(List<Channel> channelsSrc, List<Channel> channelsDst) { |
| boolean isSrcChannelsValid = true; |
| |
| Map<String, Channel> sourceMap = new HashMap<>(); |
| channelsSrc.forEach(srcChannel -> sourceMap.put(srcChannel.getName(), srcChannel)); |
| |
| for (Channel channelDst : channelsDst) { |
| if (sourceMap.get(channelDst.getName()) == null) { |
| isSrcChannelsValid = false; |
| break; |
| } |
| } |
| |
| return isSrcChannelsValid; |
| } |
| |
| private Channel replaceChannelDst(Channel channelSrc, Channel channelDst, Measurement measurementDst, |
| EntityHolder ehSrc, Transaction transaction) { |
| Channel channelNew = entityFactoryDst.createChannel(channelDst.getName(), measurementDst, |
| channelDst.getQuantity()); |
| |
| copyValues(channelDst, channelNew, Arrays.asList("Id"), false); |
| persist(transaction, channelNew); |
| |
| mapSrcDstEntities.put(new EntityHolder(channelSrc, entityManagerSrc), |
| new EntityHolder(channelNew, entityManagerDst)); |
| |
| transaction.delete(Collections.singletonList(channelDst)); |
| return channelNew; |
| } |
| |
| private Map<String, MeasuredValues> getMeasurementValuesMap(EntityManager entityManager, |
| ChannelGroup channelGroup) { |
| |
| Map<String, MeasuredValues> returnVal = new HashMap<>(); |
| |
| for (MeasuredValues measuredValues : entityManager.readMeasuredValues( |
| ReadRequest.create(channelGroup).valuesMode(ValuesMode.STORAGE).allChannels().allValues())) { |
| returnVal.put(measuredValues.getName(), measuredValues); |
| } |
| return returnVal; |
| } |
| |
| /** |
| * Preloads quantities from dst for the supplied Channels from src. |
| * |
| * @param srcChannels |
| * @return |
| */ |
| private Map<String, Optional<Quantity>> preloadQuantities(List<Channel> srcChannels) { |
| |
| LOG.trace("Preloading Quantities."); |
| |
| // Load quantity names in dst by name |
| Set<String> quantityNames = srcChannels.stream().map(c -> c.getQuantity().getName()) |
| .map(n -> quantityMapping.getOrDefault(n, n)).collect(Collectors.toSet()); |
| |
| List<Quantity> results = entityManagerDst.loadAll(Quantity.class, quantityNames); |
| |
| // Find a valid quantity with the highest version |
| /* |
| * TODO Quantity should actually implement Versionable, then we could just use |
| * org.eclipse.mdm.api.dflt.EntityManager.loadLatestValid(Class<T>, String) Bug: |
| * https://bugs.eclipse.org/bugs/show_bug.cgi?id=553368 |
| */ |
| |
| Comparator<Quantity> compareByVersion = Comparator |
| .comparing(q -> Integer.valueOf(q.getValue(Versionable.ATTR_VERSION).extract())); |
| |
| return results.stream().filter(q -> q.getValue(Versionable.ATTR_VERSION_STATE).extract() == VersionState.VALID) |
| .collect(Collectors.groupingBy(Quantity::getName, Collectors.maxBy(compareByVersion))); |
| } |
| |
| private Optional<ChannelGroup> fetchOneChannelGroup(EntityManager entityManager, ChannelGroup channelGroupSrc) { |
| Measurement measurementParentDst = (Measurement) mapSrcDstEntities |
| .get(new EntityHolder(entityManagerSrc.loadParent(channelGroupSrc, Measurement.class).get(), |
| entityManagerSrc)) |
| .getEntity(); |
| |
| return fetchChild(entityManager, measurementParentDst, ChannelGroup.class, channelGroupSrc.getName()); |
| |
| } |
| |
| private ChannelGroup copyChannelGroup(ChannelGroup channelGroupSrc, Transaction transaction, boolean append) { |
| EntityHolder ehSrc = new EntityHolder(channelGroupSrc, entityManagerSrc); |
| |
| EntityHolder ehDst = mapSrcDstEntities.get(ehSrc); |
| |
| if (null == ehDst) { |
| LOG.trace("Importing ChannelGroup '{}'", channelGroupSrc.getName()); |
| Measurement measurementParentDst = (Measurement) mapSrcDstEntities |
| .get(new EntityHolder(entityManagerSrc.loadParent(channelGroupSrc, Measurement.class).get(), |
| entityManagerSrc)) |
| .getEntity(); |
| |
| EntityType etChannelGroup = modelManagerDst.getEntityType(ChannelGroup.class); |
| EntityType etMeasurement = modelManagerDst.getEntityType(Measurement.class); |
| |
| Relation relMeasurement = etChannelGroup.getRelation(etMeasurement); |
| |
| if (null == relMeasurement) { |
| throw new ApiCopyException("No relation to MeaResult found at SubMatrix!"); |
| } |
| |
| Optional<ChannelGroup> channelGroupOptional = fetchOneChannelGroup(entityManagerDst, channelGroupSrc); |
| |
| ChannelGroup channelGroupDst = null; |
| |
| if (append && channelGroupOptional.isPresent()) { |
| transaction.delete(Collections.singletonList(channelGroupOptional.get())); |
| channelGroupDst = entityFactoryDst.createChannelGroup(channelGroupSrc.getName(), |
| channelGroupSrc.getNumberOfValues(), measurementParentDst); |
| } else { |
| channelGroupDst = channelGroupOptional |
| .orElseGet(() -> entityFactoryDst.createChannelGroup(channelGroupSrc.getName(), |
| channelGroupSrc.getNumberOfValues(), measurementParentDst)); |
| } |
| |
| copyValues(channelGroupSrc, channelGroupDst, Arrays.asList("Id"), false); |
| |
| persist(transaction, channelGroupDst); |
| |
| ehDst = new EntityHolder(channelGroupDst, entityManagerDst); |
| mapSrcDstEntities.put(ehSrc, ehDst); |
| } |
| |
| return (ChannelGroup) ehDst.getEntity(); |
| } |
| |
| private Optional<TemplateTest> loadTemplateTest(Test testSrc) { |
| Optional<TemplateTest> returnVal = Optional.empty(); |
| |
| String templateTestName = templateManager.getTemplateTestName(testSrc); |
| |
| if (!Strings.isNullOrEmpty(templateTestName)) { |
| returnVal = getCurrentValidTestTemplate(entityManagerDst.loadAll(TemplateTest.class, templateTestName)); |
| |
| } |
| |
| return returnVal; |
| } |
| |
| private Optional<TemplateTest> getCurrentValidTestTemplate(List<TemplateTest> listTemplateTests) { |
| Optional<TemplateTest> returnVal = Optional.empty(); |
| |
| if (listTemplateTests != null && !listTemplateTests.isEmpty()) { |
| int highestVersion = -1; |
| TemplateTest highestValidTemplate = null; |
| |
| for (TemplateTest templateTest : listTemplateTests) { |
| Value value = templateTest.getValue(TemplateTest.ATTR_VERSION_STATE); |
| |
| if (VersionState.VALID.equals(value.extract())) { |
| int version = Integer.parseInt(templateTest.getValue(TemplateTest.ATTR_VERSION).extract()); |
| |
| if (version > highestVersion) { |
| highestValidTemplate = templateTest; |
| highestVersion = version; |
| } |
| } |
| |
| } |
| |
| if (highestValidTemplate != null) { |
| returnVal = Optional.of(highestValidTemplate); |
| } |
| |
| } |
| return returnVal; |
| } |
| |
| private Optional<TemplateTestStep> loadTemplateTestStep(TestStep testStepSrc) { |
| Optional<TemplateTestStep> returnVal = Optional.empty(); |
| |
| String templateTestStepName = templateManager.getTemplateTestStepName(testStepSrc); |
| |
| if (!Strings.isNullOrEmpty(templateTestStepName)) { |
| returnVal = getCurrentValidTestStepTemplate( |
| entityManagerDst.loadAll(TemplateTestStep.class, templateTestStepName)); |
| } |
| |
| return returnVal; |
| } |
| |
| private Optional<TemplateTestStep> getCurrentValidTestStepTemplate(List<TemplateTestStep> listTemplateTestSteps) { |
| Optional<TemplateTestStep> returnVal = Optional.empty(); |
| |
| if (listTemplateTestSteps != null && !listTemplateTestSteps.isEmpty()) { |
| int highestVersion = -1; |
| TemplateTestStep highestValidTemplate = null; |
| |
| for (TemplateTestStep templateTestStep : listTemplateTestSteps) { |
| Value value = templateTestStep.getValue(TemplateTestStep.ATTR_VERSION_STATE); |
| |
| if (VersionState.VALID.equals(value.extract())) { |
| int version = Integer.parseInt(templateTestStep.getValue(TemplateTestStep.ATTR_VERSION).extract()); |
| |
| if (version > highestVersion) { |
| highestValidTemplate = templateTestStep; |
| highestVersion = version; |
| } |
| } |
| |
| } |
| |
| if (highestValidTemplate != null) { |
| returnVal = Optional.of(highestValidTemplate); |
| } |
| |
| } |
| return returnVal; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.mdm.apicopy.control.ApiCopyTask#setProperties(java.util.Map) |
| */ |
| @Override |
| public void setProperties(Map<String, String> properties) { |
| this.properties = properties; |
| this.replaceFileLinks = Boolean |
| .valueOf(this.properties.getOrDefault(PROPERTY_REPLACE_FILELINKS, DEFAULT_REPLACE_FILES)); |
| } |
| |
| } |