fr.inria.atlanmod.neoemf.benchmarks.datastore.helper.BackendHelper.java Source code

Java tutorial

Introduction

Here is the source code for fr.inria.atlanmod.neoemf.benchmarks.datastore.helper.BackendHelper.java

Source

/*
 * Copyright (c) 2013-2016 Atlanmod INRIA LINA Mines Nantes.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Atlanmod INRIA LINA Mines Nantes - initial API and implementation
 */

package fr.inria.atlanmod.neoemf.benchmarks.datastore.helper;

import com.google.common.collect.Maps;
import com.google.common.io.Files;

import fr.inria.atlanmod.neoemf.benchmarks.datastore.InternalBackend;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;

public class BackendHelper {

    private static final Logger log = LogManager.getLogger();

    private static final String XMI = "xmi";
    private static final String ZXMI = "zxmi";

    private static final String ZIP_FILENAME = "resources.zip";

    private static List<String> AVAILABLE_RESOURCES;
    private static Map<String, String> REGISTERED_RESOURCES;

    private BackendHelper() {
    }

    private static boolean checkValidResource(String filename) {
        checkNotNull(filename);

        checkArgument(filename.endsWith("." + XMI) || filename.endsWith("." + ZXMI),
                "'%s' is an invalid resource file. Only *.%s and *.%s files are allowed.", filename, XMI, ZXMI);

        return true;
    }

    public static File copyStore(File sourceFile) throws IOException {
        File outputFile = Workspace.newTempDirectory().resolve(sourceFile.getName()).toFile();

        log.info("Copy {} to {}", sourceFile, outputFile);

        if (sourceFile.isDirectory()) {
            FileUtils.copyDirectory(sourceFile, outputFile, true);
        } else {
            FileUtils.copyFile(sourceFile, outputFile);
        }

        return outputFile;
    }

    public static File createTempStore(File sourceFile, InternalBackend targetBackend) throws Exception {
        return createStore(sourceFile, targetBackend, Workspace.newTempDirectory());
    }

    public static File createStore(File sourceFile, InternalBackend targetBackend) throws Exception {
        return createStore(sourceFile, targetBackend, Workspace.getStoreDirectory());
    }

    private static File createStore(File sourceFile, InternalBackend targetBackend, Path targetDir)
            throws Exception {
        checkValidResource(sourceFile.getName());
        checkArgument(sourceFile.exists(), "Resource '%s' does not exist", sourceFile);

        String targetFileName = Files.getNameWithoutExtension(sourceFile.getAbsolutePath()) + "."
                + targetBackend.getStoreExtension();
        File targetFile = targetDir.resolve(targetFileName).toFile();

        if (targetFile.exists()) {
            log.info("Already existing store {}", targetFile);
            return targetFile;
        }

        ResourceSet resourceSet = loadResourceSet();

        URI sourceUri = URI.createFileURI(sourceFile.getAbsolutePath());

        Resource sourceResource = resourceSet.createResource(sourceUri);
        Resource targetResource = targetBackend.createResource(targetFile, resourceSet);

        targetBackend.initAndGetEPackage();

        log.info("Loading '{}'", sourceUri);
        Map<String, Object> loadOpts = new HashMap<>();
        if (Objects.equals(ZXMI, sourceUri.fileExtension())) {
            loadOpts.put(XMIResource.OPTION_ZIP, Boolean.TRUE);
        }
        sourceResource.load(loadOpts);

        log.info("Migrating");
        targetBackend.save(targetResource);
        targetResource.getContents().addAll(sourceResource.getContents());

        sourceResource.unload();

        log.info("Saving to '{}'", targetResource.getURI());
        targetBackend.save(targetResource);

        targetBackend.unload(targetResource);

        return targetFile;
    }

    public static File createResource(String sourceFilename, InternalBackend targetBackend) throws Exception {
        if (getRegisteredResources().containsKey(sourceFilename.toLowerCase())) {
            sourceFilename = getRegisteredResources().get(sourceFilename.toLowerCase());
        }

        File sourceFile;
        if (getZipResources().contains(sourceFilename)) {
            // Get file from the resources/resource.zip
            sourceFile = extractFromZip(sourceFilename, Workspace.getResourcesDirectory());
        } else {
            // Get the file from the file system
            sourceFile = new File(sourceFilename);
        }
        checkValidResource(sourceFile.getName());
        checkArgument(sourceFile.exists(), "Resource '%s' does not exist", sourceFile);
        return createResource(sourceFile, targetBackend);
    }

    private static File createResource(File sourceFile, InternalBackend targetBackend) throws Exception {
        String targetFileName = Files.getNameWithoutExtension(sourceFile.getName()) + "."
                + targetBackend.getResourceExtension() + "." + ZXMI;
        File targetFile = Workspace.getResourcesDirectory().resolve(targetFileName).toFile();

        if (targetFile.exists()) {
            log.info("Already existing resource {}", targetFile);
            return targetFile;
        }

        ResourceSet resourceSet = loadResourceSet();

        URI sourceURI = URI.createFileURI(sourceFile.getAbsolutePath());

        log.info("Loading '{}'", sourceURI);
        Resource sourceResource = resourceSet.getResource(sourceURI, true);

        URI targetURI = URI.createFileURI(targetFile.getAbsolutePath());
        Resource targetResource = resourceSet.createResource(targetURI);

        log.info("Migrating");
        targetResource.getContents()
                .add(migrate(sourceResource.getContents().get(0), targetBackend.initAndGetEPackage()));

        sourceResource.unload();

        log.info("Saving to '{}'", targetResource.getURI());
        Map<String, Object> saveOpts = new HashMap<>();
        saveOpts.put(XMIResource.OPTION_ZIP, Boolean.TRUE);
        targetResource.save(saveOpts);

        targetResource.unload();

        return targetFile;
    }

    /*
     * EMF migration
     */

    private static ResourceSet loadResourceSet() {
        org.eclipse.gmt.modisco.java.emf.impl.JavaPackageImpl.init();

        ResourceSet resourceSet = new ResourceSetImpl();
        resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(XMI, new XMIResourceFactoryImpl());
        resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(ZXMI, new XMIResourceFactoryImpl());
        return resourceSet;
    }

    private static EObject migrate(EObject eObject, EPackage targetEPackage) {
        Map<EObject, EObject> correspondencesMap = new HashMap<>();
        EObject returnEObject = getCorrespondingEObject(correspondencesMap, eObject, targetEPackage);
        copy(correspondencesMap, eObject, returnEObject);

        Iterable<EObject> allContents = () -> EcoreUtil.getAllContents(eObject, true);

        for (EObject sourceEObject : allContents) {
            EObject targetEObject = getCorrespondingEObject(correspondencesMap, sourceEObject, targetEPackage);
            copy(correspondencesMap, sourceEObject, targetEObject);
        }

        return returnEObject;
    }

    private static void copy(Map<EObject, EObject> correspondencesMap, EObject sourceEObject,
            EObject targetEObject) {
        for (EStructuralFeature sourceFeature : sourceEObject.eClass().getEAllStructuralFeatures()) {
            if (sourceEObject.eIsSet(sourceFeature)) {
                EStructuralFeature targetFeature = targetEObject.eClass()
                        .getEStructuralFeature(sourceFeature.getName());
                if (sourceFeature instanceof EAttribute) {
                    targetEObject.eSet(targetFeature, sourceEObject.eGet(sourceFeature));
                } else { // EReference
                    if (!sourceFeature.isMany()) {
                        targetEObject.eSet(targetFeature, getCorrespondingEObject(correspondencesMap,
                                (EObject) sourceEObject.eGet(targetFeature), targetEObject.eClass().getEPackage()));
                    } else {
                        List<EObject> targetList = new BasicEList<>();

                        @SuppressWarnings({ "unchecked" })
                        Iterable<EObject> sourceList = (Iterable<EObject>) sourceEObject.eGet(sourceFeature);
                        for (EObject aSourceList : sourceList) {
                            targetList.add(getCorrespondingEObject(correspondencesMap, aSourceList,
                                    targetEObject.eClass().getEPackage()));
                        }
                        targetEObject.eSet(targetFeature, targetList);
                    }
                }
            }
        }
    }

    private static EObject getCorrespondingEObject(Map<EObject, EObject> correspondencesMap, EObject eObject,
            EPackage ePackage) {
        EObject targetEObject = correspondencesMap.get(eObject);
        if (isNull(targetEObject)) {
            EClass eClass = eObject.eClass();
            EClass targetClass = (EClass) ePackage.getEClassifier(eClass.getName());
            targetEObject = EcoreUtil.create(targetClass);
            correspondencesMap.put(eObject, targetEObject);
        }
        return targetEObject;
    }

    /*
     * ZIP extraction
     */

    private static List<String> getZipResources() throws IOException {
        if (isNull(AVAILABLE_RESOURCES)) {
            AVAILABLE_RESOURCES = new ArrayList<>();

            try (ZipInputStream inputStream = new ZipInputStream(
                    BackendHelper.class.getResourceAsStream("/" + ZIP_FILENAME))) {
                ZipEntry entry = inputStream.getNextEntry();
                while (nonNull(entry)) {
                    if (!entry.isDirectory() && checkValidResource(entry.getName())) {
                        AVAILABLE_RESOURCES.add(new File(entry.getName()).getName());
                    }
                    inputStream.closeEntry();
                    entry = inputStream.getNextEntry();
                }
            }
        }
        return AVAILABLE_RESOURCES;
    }

    private static Map<String, String> getRegisteredResources() throws IOException {
        if (isNull(REGISTERED_RESOURCES)) {
            Properties properties = new Properties();
            properties.load(BackendHelper.class.getResourceAsStream("/resources.properties"));
            REGISTERED_RESOURCES = Maps.fromProperties(properties);
        }
        return REGISTERED_RESOURCES;
    }

    private static File extractFromZip(String filename, Path outputDir) throws IOException {
        File outputFile = null;
        boolean fileFound = false;
        try (ZipInputStream inputStream = new ZipInputStream(
                BackendHelper.class.getResourceAsStream("/" + ZIP_FILENAME))) {
            ZipEntry entry = inputStream.getNextEntry();
            while (nonNull(entry) || !fileFound) {
                if (!entry.isDirectory() && Objects.equals(new File(entry.getName()).getName(), filename)) {
                    outputFile = extractEntryFromZip(inputStream, entry, outputDir);
                    fileFound = true;
                }
                inputStream.closeEntry();
                entry = inputStream.getNextEntry();
            }
        }
        return outputFile;
    }

    private static File extractEntryFromZip(ZipInputStream inputStream, ZipEntry entry, Path outputDir)
            throws IOException {
        File outputFile = outputDir.resolve(new File(entry.getName()).getName()).toFile();
        if (outputFile.exists()) {
            log.info("Already extracted resource {}", outputFile);
            return outputFile;
        }
        IOUtils.copy(inputStream, new FileOutputStream(outputFile));
        return outputFile;
    }
}