blob: c35ebd7552663dfb49bc43f32da95e6d9104c390 [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.apicopy.control;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.mdm.api.base.Transaction;
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.ContextDescribable;
import org.eclipse.mdm.api.base.model.ContextRoot;
import org.eclipse.mdm.api.base.model.ContextSensor;
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.PhysicalDimension;
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.dflt.ApplicationContext;
import org.eclipse.mdm.api.dflt.model.CatalogAttribute;
import org.eclipse.mdm.api.dflt.model.CatalogComponent;
import org.eclipse.mdm.api.dflt.model.CatalogSensor;
import org.eclipse.mdm.api.dflt.model.Pool;
import org.eclipse.mdm.api.dflt.model.Project;
import org.eclipse.mdm.api.dflt.model.TemplateRoot;
import org.eclipse.mdm.api.dflt.model.TemplateTestStep;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.ListMultimap;
public class ExportTask extends TransferBase implements ApiCopyTask {
private static final Logger LOG = LoggerFactory.getLogger(ExportTask.class);
public ExportTask(ApplicationContext src, ApplicationContext dst) {
super(src, dst);
}
@Override
public void copy(List<? extends Entity> entities) {
Transaction transaction = entityManagerDst.startTransaction();
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("Importing entities: {}", entities);
entities.forEach(e -> copyEntity(e, true, transaction));
transaction.commit();
} catch (Exception exc) {
try {
transaction.abort();
} catch (Exception exc2) {
LOG.error("Could not abort transaction!");
}
throw new ApiCopyException("Could not copy data.", exc);
}
}
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, 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) {
LOG.trace("Exporting Project '{}'", projectSrc.getName());
Project projectDst = entityFactoryDst.createProject(projectSrc.getName());
copyValues(projectSrc, projectDst, Arrays.asList("Id", "Name"));
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("Exporting Pool '{}'", poolSrc.getName());
Project projectParentDst = (Project) mapSrcDstEntities
.get(new EntityHolder(entityManagerSrc.loadParent(poolSrc, Project.class).get(), entityManagerSrc))
.getEntity();
Pool poolDst = entityFactoryDst.createPool(poolSrc.getName(), projectParentDst);
copyValues(poolSrc, poolDst, Arrays.asList("Id", "Name"));
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) {
LOG.trace("Exporting Test '{}'", testSrc.getName());
Pool poolParentDst = (Pool) mapSrcDstEntities
.get(new EntityHolder(entityManagerSrc.loadParent(testSrc, Pool.class).get(), entityManagerSrc))
.getEntity();
Test testDst = entityFactoryDst.createTest(testSrc.getName(), poolParentDst);
copyValues(testSrc, testDst, Arrays.asList("Id", "Name"));
persist(transaction, testDst);
ehDst = new EntityHolder(testDst, entityManagerDst);
mapSrcDstEntities.put(ehSrc, ehDst);
if (recursive) {
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("Exporting TestStep '{}'", testStepSrc.getName());
Test testParentDst = (Test) mapSrcDstEntities
.get(new EntityHolder(entityManagerSrc.loadParent(testStepSrc, Test.class).get(), entityManagerSrc))
.getEntity();
TestStep testStepDst = entityFactoryDst.createTestStep(testStepSrc.getName(), testParentDst);
copyValues(testStepSrc, testStepDst, Arrays.asList("Id", "Name"));
persist(transaction, testStepDst);
TemplateTestStep tpl = entityManagerSrc.loadTemplate(testStepSrc).orElseThrow(() -> new ApiCopyException(
"Could not retrieve TemplateTestStep for TestStep " + testStepSrc.getID()));
copyContext(testStepSrc, testStepDst, tpl, transaction);
ehDst = new EntityHolder(testStepDst, entityManagerDst);
mapSrcDstEntities.put(ehSrc, ehDst);
if (recursive) {
entityManagerSrc.loadChildren(testStepSrc, Measurement.class)
.forEach(measurement -> copyMeasurement(measurement, recursive, transaction));
}
}
return (TestStep) ehDst.getEntity();
}
private Measurement copyMeasurement(Measurement measurementSrc, boolean recursive, Transaction transaction) {
EntityHolder ehSrc = new EntityHolder(measurementSrc, entityManagerSrc);
EntityHolder ehDst = mapSrcDstEntities.get(ehSrc);
if (null == ehDst) {
LOG.trace("Exporting Measurement '{}'", measurementSrc.getName());
TestStep testStepParentSrc = entityManagerSrc.loadParent(measurementSrc, TestStep.class).get();
TestStep testStepParentDst = (TestStep) mapSrcDstEntities
.get(new EntityHolder(testStepParentSrc, entityManagerSrc)).getEntity();
Measurement measurementDst = entityFactoryDst.createMeasurement(measurementSrc.getName(),
testStepParentDst);
copyValues(measurementSrc, measurementDst, Arrays.asList("Id", "Name"));
persist(transaction, measurementDst);
TemplateTestStep tpl = entityManagerSrc.loadTemplate(testStepParentSrc)
.orElseThrow(() -> new ApiCopyException(
"Could not retrieve TemplateTestStep for Measurement + " + measurementSrc.getID()));
copyContext(measurementSrc, measurementDst, tpl, transaction);
ehDst = new EntityHolder(measurementDst, entityManagerDst);
mapSrcDstEntities.put(ehSrc, ehDst);
if (recursive) {
List<WriteRequest> listWriteRequests = new ArrayList<>();
Map<String, Channel> mapChannels = new HashMap<>();
for (Channel channel : entityManagerSrc.loadChildren(measurementSrc, Channel.class)) {
Channel channelDst = copyChannel(channel, transaction);
mapChannels.put(channel.getName(), channelDst);
}
for (ChannelGroup channelGroup : entityManagerSrc.loadChildren(measurementSrc, ChannelGroup.class)) {
ChannelGroup channelGroupDst = copyChannelGroup(channelGroup, transaction);
for (MeasuredValues measuredValues : entityManagerSrc.readMeasuredValues(ReadRequest
.create(channelGroup).valuesMode(ValuesMode.STORAGE).allChannels().allValues())) {
LOG.trace("Exporting MeasuredValues '{}'", measuredValues.getName());
if (!mapChannels.containsKey(measuredValues.getName())) {
throw new ApiCopyException(
String.format("Cannot find Channel %s in destination!", measuredValues.getName()));
}
Channel channelDst = mapChannels.get(measuredValues.getName());
listWriteRequests.add(createWriteRequest(channelGroupDst, channelDst, measuredValues));
}
}
transaction.writeMeasuredValues(listWriteRequests);
}
}
return (Measurement) ehDst.getEntity();
}
private void copyContext(ContextDescribable entitySrc, ContextDescribable entityDst, TemplateTestStep tpl,
Transaction transaction) {
for (ContextRoot root : entitySrc.loadContexts(entityManagerSrc).values()) {
LOG.trace("Exporting ContextRoot '{}'", root.getName());
TemplateRoot tplRoot = tpl.getTemplateRoot(root.getContextType())
.orElseThrow(() -> new ApiCopyException("Could not retrieve TemplateRoot " + root.getContextType()
+ " for TestStep + " + entitySrc.getID()));
ContextRoot rootDst;
if (entityDst instanceof TestStep) {
rootDst = entityFactoryDst.createContextRoot((TestStep) entityDst, tplRoot);
} else if (entityDst instanceof Measurement) {
rootDst = entityFactoryDst.createContextRoot((Measurement) entityDst, tplRoot);
} else {
throw new ApiCopyException("ContextDescribable must be of instance TestStep or Measurement!");
}
copyValues(root, rootDst, Arrays.asList("Id", "Name"));
persist(transaction, rootDst);
for (ContextComponent comp : root.getContextComponents()) {
LOG.trace("Exporting ContextComponent '{}'", comp.getName());
rootDst.getContextComponent(comp.getName()).ifPresent(c -> {
copyValues(comp, c, Arrays.asList("Id", "Name"));
persist(transaction, c);
});
}
for (ContextSensor sensor : root.getContextSensors()) {
LOG.trace("Exporting ContextSensor '{}'", sensor.getName());
// Parent should be already created above
ContextComponent parentDst = rootDst.getContextComponent(sensor.getContextComponent().getName())
.orElseThrow(() -> new ApiCopyException(
"Parent ContextComponent of sensor " + sensor.getName() + " not found!"));
ContextSensor sensorDst = parentDst.getContextSensor(sensor.getName()).orElseThrow(
() -> new ApiCopyException("ContextSensor '" + sensor.getName() + "' not found in target!"));
copyValues(sensor, sensorDst, Arrays.asList("Id", "Name"));
persist(transaction, sensorDst);
}
}
persist(transaction, entityDst);
}
private Channel copyChannel(Channel channelSrc, Transaction transaction) {
EntityHolder ehSrc = new EntityHolder(channelSrc, entityManagerSrc);
EntityHolder ehDst = mapSrcDstEntities.get(ehSrc);
if (null == ehDst) {
LOG.trace("Exporting Channel '{}'", channelSrc.getName());
Measurement measurementParentDst = (Measurement) mapSrcDstEntities
.get(new EntityHolder(entityManagerSrc.loadParent(channelSrc, Measurement.class).get(),
entityManagerSrc))
.getEntity();
Quantity quantitySrc = channelSrc.getQuantity();
Unit unitSrc = quantitySrc.getDefaultUnit();
PhysicalDimension physicalDimensionSrc = unitSrc.getPhysicalDimension();
PhysicalDimension physicalDimensionDst = fetchOne(entityManagerDst, PhysicalDimension.class,
physicalDimensionSrc.getName())
.orElseGet(() -> entityFactoryDst.createPhysicalDimension(physicalDimensionSrc.getName()));
if (isNewEntity(physicalDimensionDst)) {
copyValues(physicalDimensionSrc, physicalDimensionDst, Arrays.asList("Id", "Name"));
persist(transaction, physicalDimensionDst);
}
Unit unitDst = fetchOne(entityManagerDst, Unit.class, unitSrc.getName())
.orElseGet(() -> entityFactoryDst.createUnit(unitSrc.getName(), physicalDimensionDst));
if (isNewEntity(unitDst)) {
copyValues(unitSrc, unitDst, Arrays.asList("Id", "Name"));
persist(transaction, unitDst);
}
Quantity quantityDst = fetchOne(entityManagerDst, Quantity.class, quantitySrc.getName())
.orElseGet(() -> entityFactoryDst.createQuantity(quantitySrc.getName(), unitDst));
if (isNewEntity(quantityDst)) {
copyValues(quantitySrc, quantityDst, Arrays.asList("Id", "Name"));
persist(transaction, quantityDst);
}
Channel channelDst = entityFactoryDst.createChannel(channelSrc.getName(), measurementParentDst,
quantityDst);
copyValues(channelSrc, channelDst, Arrays.asList("Id", "Name"));
persist(transaction, channelDst);
ehDst = new EntityHolder(channelDst, entityManagerDst);
mapSrcDstEntities.put(ehSrc, ehDst);
}
return (Channel) ehDst.getEntity();
}
private ChannelGroup copyChannelGroup(ChannelGroup channelGroupSrc, Transaction transaction) {
EntityHolder ehSrc = new EntityHolder(channelGroupSrc, entityManagerSrc);
EntityHolder ehDst = mapSrcDstEntities.get(ehSrc);
if (null == ehDst) {
LOG.trace("Exporting ChannelGroup '{}'", channelGroupSrc.getName());
Measurement measurementParentDst = (Measurement) mapSrcDstEntities
.get(new EntityHolder(entityManagerSrc.loadParent(channelGroupSrc, Measurement.class).get(),
entityManagerSrc))
.getEntity();
ChannelGroup channelGroupDst = entityFactoryDst.createChannelGroup(channelGroupSrc.getName(),
channelGroupSrc.getNumberOfValues(), measurementParentDst);
copyValues(channelGroupSrc, channelGroupDst, Arrays.asList("Id", "Name"));
persist(transaction, channelGroupDst);
ehDst = new EntityHolder(channelGroupDst, entityManagerDst);
mapSrcDstEntities.put(ehSrc, ehDst);
}
return (ChannelGroup) ehDst.getEntity();
}
/**
* Copy the MDM catalog.
*/
public void copyCatalog() {
Transaction catTransaction = entityManagerDst.startTransaction();
try {
mapSrcDstEntities.clear();
LOG.trace("Exporting Catalog");
// Copy catalog
List<CatalogComponent> catComps = new ArrayList<>();
for (ContextType contextType : ContextType.values()) {
for (CatalogComponent catComp : entityManagerSrc.loadAll(CatalogComponent.class, contextType)) {
LOG.trace("Exporting CatalogComponent '{}'", catComp.getName());
CatalogComponent catCompDst = entityFactoryDst.createCatalogComponent(catComp.getContextType(),
catComp.getName());
for (CatalogAttribute catAttr : catComp.getCatalogAttributes()) {
if (catAttr.getValueType().isEnumerationType()) {
entityFactoryDst.createCatalogAttribute(catAttr.getName(), catAttr.getEnumerationObject(),
catCompDst);
} else {
entityFactoryDst.createCatalogAttribute(catAttr.getName(), catAttr.getValueType(),
catCompDst);
}
}
for (CatalogSensor catSensor : catComp.getCatalogSensors()) {
LOG.trace("Exporting CatalogSensor '{}'", catComp.getName());
CatalogSensor catSensorDst = entityFactoryDst.createCatalogSensor(catSensor.getName(),
catCompDst);
for (CatalogAttribute catAttr : catSensor.getCatalogAttributes()) {
entityFactoryDst.createCatalogSensorAttribute(catAttr.getName(), catAttr.getValueType(),
catSensorDst);
}
}
catComps.add(catCompDst);
}
}
catTransaction.create(catComps);
catTransaction.commit();
} catch (Exception exc) {
try {
catTransaction.abort();
} catch (Exception exc2) {
LOG.error("Could not abort transaction!");
}
throw new ApiCopyException("Could not copy data.", exc);
}
}
}