ATFX Import of external references
Conflicts:
org.eclipse.mdm.api.atfxadapter/src/main/java/org/eclipse/mdm/api/atfxadapter/ATFXContext.java
org.eclipse.mdm.api.atfxadapter/src/main/java/org/eclipse/mdm/api/atfxadapter/ATFXContextFactory.java
org.eclipse.mdm.apicopy/src/main/java/org/eclipse/mdm/apicopy/control/ImportTask.java
org.eclipse.mdm.apicopy/src/main/java/org/eclipse/mdm/apicopy/control/TransferBase.java
Signed-off-by: Alexander Knoblauch <a.knoblauch@peak-solution.de>
diff --git a/org.eclipse.mdm.api.atfxadapter/src/main/java/org/eclipse/mdm/api/atfxadapter/filetransfer/ATFXFileService.java b/org.eclipse.mdm.api.atfxadapter/src/main/java/org/eclipse/mdm/api/atfxadapter/filetransfer/ATFXFileService.java
new file mode 100644
index 0000000..f83516a
--- /dev/null
+++ b/org.eclipse.mdm.api.atfxadapter/src/main/java/org/eclipse/mdm/api/atfxadapter/filetransfer/ATFXFileService.java
@@ -0,0 +1,219 @@
+/**
+ *
+ */
+package org.eclipse.mdm.api.atfxadapter.filetransfer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.time.Duration;
+import java.time.LocalTime;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.stream.Collectors;
+
+import org.eclipse.mdm.api.base.file.FileService;
+import org.eclipse.mdm.api.base.model.Entity;
+import org.eclipse.mdm.api.base.model.FileLink;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author akn
+ *
+ */
+public class ATFXFileService implements FileService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ATFXFileService.class);
+
+ private final Path parentDirectory;
+
+ public ATFXFileService(File parentDirectory) {
+ this.parentDirectory = parentDirectory.toPath();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.mdm.api.base.file.FileService#downloadSequential(org.eclipse.mdm.
+ * api.base.model.Entity, java.nio.file.Path, java.util.Collection,
+ * org.eclipse.mdm.api.base.file.FileService.ProgressListener)
+ */
+ @Override
+ public void downloadSequential(Entity entity, Path target, Collection<FileLink> fileLinks,
+ ProgressListener progressListener) throws IOException {
+ Map<String, List<FileLink>> groups = fileLinks.stream().filter(FileLink::isRemote)
+ .collect(Collectors.groupingBy(FileLink::getRemotePath));
+
+ long totalSize = calculateDownloadSize(groups);
+ final AtomicLong transferred = new AtomicLong();
+ LocalTime start = LocalTime.now();
+ UUID id = UUID.randomUUID();
+ LOGGER.debug("Sequential download of {} file(s) with id '{}' started.", groups.size(), id);
+ for (List<FileLink> group : groups.values()) {
+ FileLink fileLink = group.get(0);
+
+ download(entity, target, fileLink, (b, p) -> {
+ double tranferredBytes = transferred.addAndGet(b);
+ if (progressListener != null) {
+ progressListener.progress(b, (float) (tranferredBytes / totalSize));
+ }
+ });
+
+ for (FileLink other : group.subList(1, group.size())) {
+ other.setLocalStream(fileLink.getLocalStream());
+ }
+ }
+ LOGGER.debug("Sequential download with id '{}' finished in {}.", id, Duration.between(start, LocalTime.now()));
+
+ }
+
+ private long calculateDownloadSize(Map<String, List<FileLink>> groups) {
+ List<FileLink> links = groups.values().stream().map(l -> l.get(0)).collect(Collectors.toList());
+ long totalSize = 0;
+ for (FileLink fileLink : links) {
+ File f = new File(fileLink.getRemotePath());
+ // overflow may occur in case of total size exceeds 9223 PB!
+ totalSize = Math.addExact(totalSize, f.length());
+ }
+
+ return totalSize;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.mdm.api.base.file.FileService#downloadParallel(org.eclipse.mdm.
+ * api.base.model.Entity, java.nio.file.Path, java.util.Collection,
+ * org.eclipse.mdm.api.base.file.FileService.ProgressListener)
+ */
+ @Override
+ public void downloadParallel(Entity entity, Path target, Collection<FileLink> fileLinks,
+ ProgressListener progressListener) throws IOException {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.mdm.api.base.file.FileService#download(org.eclipse.mdm.api.base.
+ * model.Entity, java.nio.file.Path, org.eclipse.mdm.api.base.model.FileLink,
+ * org.eclipse.mdm.api.base.file.FileService.ProgressListener)
+ */
+ @Override
+ public void download(Entity entity, Path target, FileLink fileLink, ProgressListener progressListener)
+ throws IOException {
+ if (Files.exists(target)) {
+ if (!Files.isDirectory(target)) {
+ throw new IllegalArgumentException("Target path is not a directory.");
+ }
+ } else {
+ Files.createDirectory(target);
+ }
+
+ try (InputStream inputStream = openStream(entity, fileLink)) {
+ Path absolutePath = target.resolve(fileLink.getFileName()).toAbsolutePath();
+ String remotePath = fileLink.getRemotePath();
+ LOGGER.debug("Starting download of file '{}' to '{}'.", remotePath, absolutePath);
+ LocalTime start = LocalTime.now();
+ Files.copy(inputStream, absolutePath);
+ LOGGER.debug("File '{}' successfully downloaded in {} to '{}'.", remotePath,
+ Duration.between(start, LocalTime.now()), absolutePath);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.mdm.api.base.file.FileService#openStream(org.eclipse.mdm.api.base
+ * .model.Entity, org.eclipse.mdm.api.base.model.FileLink,
+ * org.eclipse.mdm.api.base.file.FileService.ProgressListener)
+ */
+ @Override
+ public InputStream openStream(Entity entity, FileLink fileLink, ProgressListener progressListener)
+ throws IOException {
+
+ return new FileInputStream(parentDirectory.resolve(fileLink.getRemotePath()).toFile());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.mdm.api.base.file.FileService#loadSize(org.eclipse.mdm.api.base.
+ * model.Entity, org.eclipse.mdm.api.base.model.FileLink)
+ */
+ @Override
+ public void loadSize(Entity entity, FileLink fileLink) throws IOException {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.mdm.api.base.file.FileService#uploadSequential(org.eclipse.mdm.
+ * api.base.model.Entity, java.util.Collection,
+ * org.eclipse.mdm.api.base.file.FileService.ProgressListener)
+ */
+ @Override
+ public void uploadSequential(Entity entity, Collection<FileLink> fileLinks, ProgressListener progressListener)
+ throws IOException {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.mdm.api.base.file.FileService#uploadParallel(org.eclipse.mdm.api.
+ * base.model.Entity, java.util.Collection,
+ * org.eclipse.mdm.api.base.file.FileService.ProgressListener)
+ */
+ @Override
+ public void uploadParallel(Entity entity, Collection<FileLink> fileLinks, ProgressListener progressListener)
+ throws IOException {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.mdm.api.base.file.FileService#delete(org.eclipse.mdm.api.base.
+ * model.Entity, java.util.Collection)
+ */
+ @Override
+ public void delete(Entity entity, Collection<FileLink> fileLinks) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.eclipse.mdm.api.base.file.FileService#delete(org.eclipse.mdm.api.base.
+ * model.Entity, org.eclipse.mdm.api.base.model.FileLink)
+ */
+ @Override
+ public void delete(Entity entity, FileLink fileLink) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/org.eclipse.mdm.apicopy/src/main/java/org/eclipse/mdm/apicopy/control/TransferBase.java b/org.eclipse.mdm.apicopy/src/main/java/org/eclipse/mdm/apicopy/control/TransferBase.java
index e3bf757..7d335e8 100644
--- a/org.eclipse.mdm.apicopy/src/main/java/org/eclipse/mdm/apicopy/control/TransferBase.java
+++ b/org.eclipse.mdm.apicopy/src/main/java/org/eclipse/mdm/apicopy/control/TransferBase.java
@@ -13,9 +13,12 @@
********************************************************************************/
package org.eclipse.mdm.apicopy.control;
+import java.io.IOException;
+import java.nio.file.Path;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -26,6 +29,7 @@
import org.eclipse.mdm.api.base.ServiceNotProvidedException;
import org.eclipse.mdm.api.base.Transaction;
import org.eclipse.mdm.api.base.adapter.ModelManager;
+import org.eclipse.mdm.api.base.file.FileService;
import org.eclipse.mdm.api.base.massdata.AnyTypeValuesBuilder;
import org.eclipse.mdm.api.base.massdata.ComplexNumericalValuesBuilder;
import org.eclipse.mdm.api.base.massdata.NumericalValuesBuilder;
@@ -45,6 +49,7 @@
import org.eclipse.mdm.api.base.model.Test;
import org.eclipse.mdm.api.base.model.TestStep;
import org.eclipse.mdm.api.base.model.Value;
+import org.eclipse.mdm.api.base.model.ValueType;
import org.eclipse.mdm.api.base.query.Filter;
import org.eclipse.mdm.api.base.search.SearchService;
import org.eclipse.mdm.api.dflt.ApplicationContext;
@@ -57,6 +62,7 @@
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
+import com.google.common.io.Files;
public abstract class TransferBase {
List<Class<? extends Entity>> supportedRootEntities = Arrays.asList(Project.class, Pool.class, Test.class,
@@ -69,6 +75,8 @@
EntityManager entityManagerDst;
EntityFactory entityFactoryDst;
ModelManager modelManagerDst;
+ FileService fileServiceDst;
+ FileService fileServiceSrc;
Map<EntityHolder, EntityHolder> mapSrcDstEntities = new HashMap<>();
@@ -84,6 +92,15 @@
.orElseThrow(() -> new ServiceNotProvidedException(EntityFactory.class));
modelManagerDst = contextDst.getModelManager()
.orElseThrow(() -> new ServiceNotProvidedException(ModelManager.class));
+
+ if (contextDst.getFileService().isPresent()) {
+ fileServiceDst = contextDst.getFileService().get();
+ }
+
+ if (contextSrc.getFileService().isPresent()) {
+ fileServiceSrc = contextSrc.getFileService().get();
+ }
+
}
ListMultimap<Class<? extends Entity>, Entity> loadParents(List<? extends Entity> entities) {
@@ -168,15 +185,75 @@
for (Map.Entry<String, Value> me : srcEntity.getValues().entrySet()) {
String key = me.getKey();
if (!ignoredAttributes.contains(key) && valueNamesDst.contains(key)) {
- dstEntity.getValue(me.getKey()).set(me.getValue().extract());
+ Value valueSrc = me.getValue();
+
+ if (isFileLinkDataType(valueSrc.getValueType())) {
+ uploadFiles(srcEntity, dstEntity, valueSrc);
+ }
+
+ dstEntity.getValue(me.getKey()).set(valueSrc.extract());
Value value = dstEntity.getValue(me.getKey());
- value.set(me.getValue().extract());
- value.setValid(me.getValue().isValid());
+ value.set(valueSrc.extract());
+ value.setValid(valueSrc.isValid());
}
}
}
+ /**
+ *
+ * @param valueType
+ * @return
+ */
+ private boolean isFileLinkDataType(ValueType<?> valueType) {
+ boolean isFileDataType = false;
+
+ if (ValueType.FILE_LINK_SEQUENCE.equals(valueType) || ValueType.FILE_LINK.equals(valueType)) {
+ isFileDataType = true;
+ }
+ return isFileDataType;
+ }
+
+ private void uploadFiles(Entity srcEntity, Entity dstEntity, Value valueSrc) {
+ try {
+ if (fileServiceSrc != null && fileServiceDst != null) {
+
+ if (ValueType.FILE_LINK_SEQUENCE.equals(valueSrc.getValueType())) {
+
+ List<FileLink> fileLinkList = downloadSourceFiles(srcEntity,
+ Arrays.asList(valueSrc.extract(ValueType.FILE_LINK_SEQUENCE)));
+ fileServiceDst.uploadSequential(dstEntity, fileLinkList, null);
+ valueSrc.set(fileLinkList.toArray(new FileLink[fileLinkList.size()]));
+ } else if (ValueType.FILE_LINK.equals(valueSrc.getValueType())) {
+ FileLink fileLink = downloadSourceFile(srcEntity, valueSrc.extract(ValueType.FILE_LINK));
+ fileServiceDst.uploadSequential(dstEntity, Collections.singletonList(fileLink), null);
+ valueSrc.set(fileLink);
+ }
+ }
+
+ } catch (IOException e) {
+ throw new ApiCopyException(e.getLocalizedMessage(), e);
+ }
+
+ }
+
+ private List<FileLink> downloadSourceFiles(Entity srcEntity, List<FileLink> fileLinkList) throws IOException {
+ List<FileLink> returnList = new ArrayList<FileLink>();
+
+ for (FileLink fileLink : fileLinkList) {
+ returnList.add(downloadSourceFile(srcEntity, fileLink));
+ }
+
+ return returnList;
+ }
+
+ private FileLink downloadSourceFile(Entity srcEntity, FileLink fileLinkSrc) throws IOException {
+ Path targetPath = Files.createTempDir().toPath();
+ Path filePathAbsolute = targetPath.resolve(fileLinkSrc.getFileName());
+ fileServiceSrc.download(srcEntity, targetPath, fileLinkSrc);
+ return FileLink.newLocal(filePathAbsolute);
+ }
+
WriteRequest createWriteRequest(ChannelGroup channelGroupDst, Channel channelDst, MeasuredValues measuredValues) {
WriteRequestBuilder wrb = WriteRequest.create(channelGroupDst, channelDst, measuredValues.getAxisType());
NumericalValuesBuilder builder = null;