fr.inria.atlanmod.discoverer.JsonMultiInjector.java Source code

Java tutorial

Introduction

Here is the source code for fr.inria.atlanmod.discoverer.JsonMultiInjector.java

Source

/*******************************************************************************
 * Copyright (c) 2008, 2013
 * 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:
 *    Javier Canovas (javier.canovas@inria.fr) 
 *******************************************************************************/

package fr.inria.atlanmod.discoverer;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
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 com.google.gson.JsonElement;
import com.google.gson.JsonObject;

import fr.inria.atlanmod.json.discoverer.coverage.AttMapping;
import fr.inria.atlanmod.json.discoverer.coverage.ConceptMapping;
import fr.inria.atlanmod.json.discoverer.coverage.Coverage;
import fr.inria.atlanmod.json.discoverer.coverage.CoverageMapping;
import fr.inria.atlanmod.json.discoverer.coverage.RefMapping;

/**
 * Injects a model wich information coming from several JSON files
 * This implementation does not depend on Xtext
 * 
 * @author Javier Canovas (javier.canovas@inria.fr)
 *
 */
public class JsonMultiInjector {
    private List<EObject> currentModel;
    private SingleJsonSource source1, source2;
    private Coverage coverage1, coverage2;

    private final static Logger LOGGER = Logger.getLogger(JsonMultiInjector.class.getName());

    public JsonMultiInjector(SingleJsonSource source1, Coverage coverage1, SingleJsonSource source2,
            Coverage coverage2) {
        if (source1 == null || source1.getJsonData().size() == 0)
            throw new IllegalArgumentException("Source1 cannot be null or have not json definitions");
        if (coverage1 == null)
            throw new IllegalArgumentException("Coverage1 cannot be null");
        if (source2 == null || source2.getJsonData().size() == 0)
            throw new IllegalArgumentException("Source2 cannot be null or have not json definitions");
        if (coverage2 == null)
            throw new IllegalArgumentException("Coverage2 cannot be null");

        this.source1 = source1;
        this.coverage1 = coverage1;
        this.source2 = source2;
        this.coverage2 = coverage2;
    }

    public void multiInject(File resultFile) throws FileNotFoundException {
        currentModel = new ArrayList<EObject>();

        inject(source1.getJsonData().get(0).getData(), source1.getMetamodel(), coverage1);
        inject(source2.getJsonData().get(0).getData(), source2.getMetamodel(), coverage2);

        saveModel(resultFile, currentModel);
    }

    protected void inject(JsonElement rootElement, EPackage metamodel, Coverage coverage)
            throws FileNotFoundException {
        List<JsonObject> elements = new ArrayList<JsonObject>();
        if (rootElement.isJsonArray()) {
            LOGGER.finer("Several objects found");
            for (int i = 0; i < rootElement.getAsJsonArray().size(); i++)
                if (rootElement.getAsJsonArray().get(i).isJsonObject())
                    elements.add(rootElement.getAsJsonArray().get(i).getAsJsonObject());
        } else if (rootElement.isJsonObject()) {
            LOGGER.finer("Only one object found");
            elements.add(rootElement.getAsJsonObject());
        } else {
            LOGGER.finest("The root element was " + rootElement.getClass().getName());
            LOGGER.finest("It is: " + rootElement.getAsString());
        }

        EClassifier eClassifier = metamodel.getEClassifier("Root");
        for (JsonObject jsonObject : elements) {
            EObject eObject = instantiateEClassifier(eClassifier, jsonObject, null, coverage, metamodel);
        }

    }

    protected EObject instantiateEClassifier(EClassifier eClassifier, JsonObject jsonObject,
            EClassifier compositeEClassifier, Coverage coverage, EPackage metamodel) {
        EObject result = null;
        EObject compositeResult = null;

        if (eClassifier instanceof EClass) {
            EClass eClass = (EClass) eClassifier;
            result = EcoreUtil.create(eClass);

            EClass compositeEClass = (EClass) findCompositeEClass(eClass, coverage);
            EObject existingCompositeEObject = findExistingEObject(eClass, jsonObject, compositeEClass, coverage,
                    metamodel);
            if (existingCompositeEObject != null) {
                return existingCompositeEObject;
            }

            compositeResult = EcoreUtil.create(compositeEClass);
            currentModel.add(compositeResult);

            Iterator<Map.Entry<String, JsonElement>> pairs = jsonObject.entrySet().iterator();
            while (pairs.hasNext()) {
                Map.Entry<String, JsonElement> pair = pairs.next();

                String pairId = pair.getKey();
                JsonElement value = pair.getValue();

                EStructuralFeature eStructuralFeature = eClass.getEStructuralFeature(pairId);
                if (eStructuralFeature != null) {
                    if (value.isJsonArray()) {
                        for (int i = 0; i < value.getAsJsonArray().size(); i++) {
                            JsonElement singleValue = value.getAsJsonArray().get(i);
                            if (singleValue.isJsonObject()) // TODO What happens if it is not a jsonObject?
                                setStructuralFeature(result, eStructuralFeature, singleValue, compositeResult,
                                        coverage, metamodel);
                        }
                    } else {
                        setStructuralFeature(result, eStructuralFeature, value, compositeResult, coverage,
                                metamodel);
                    }
                }
            }
        }

        return compositeResult;
    }

    private EObject findExistingEObject(EClass eClass, JsonObject jsonObject, EClass compositeEClass,
            Coverage coverage, EPackage metamodel) {
        List<EClass> existingEclasses = new ArrayList<EClass>();
        for (EObject object : currentModel) {
            EClass existingEClass = object.eClass();
            if (existingEClass.getName().equals(compositeEClass.getName())) {
                existingEclasses.add(existingEClass);

                Iterator<Map.Entry<String, JsonElement>> pairs = jsonObject.entrySet().iterator();
                while (pairs.hasNext()) {
                    Map.Entry<String, JsonElement> pair = pairs.next();

                    if (pair.getValue().isJsonPrimitive() && pair.getValue().getAsJsonPrimitive().isString()) {
                        String existingPairId = pair.getKey();
                        String existingValue = pair.getValue().getAsJsonPrimitive().toString();
                        EStructuralFeature existingEStructuralFeature = eClass
                                .getEStructuralFeature(existingPairId);
                        if (existingEStructuralFeature instanceof EAttribute
                                && existingEStructuralFeature.getEType().equals(EcorePackage.Literals.ESTRING)) {
                            EAttribute existingEAttribute = (EAttribute) existingEStructuralFeature;
                            EAttribute compositeEAttribute = (EAttribute) findCompositeEAttribute(
                                    existingEAttribute, coverage);
                            if (compositeEAttribute != null) {
                                for (EStructuralFeature objectEAttribute : existingEClass
                                        .getEStructuralFeatures()) {
                                    if (objectEAttribute.getName().equals(compositeEAttribute.getName())) {
                                        String compositeValue = (String) object.eGet(objectEAttribute);
                                        if (existingValue.equals(compositeValue))
                                            return object;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return null;
    }

    protected void setStructuralFeature(EObject result, EStructuralFeature eStructuralFeature, JsonElement value,
            EObject compositeResult, Coverage coverage, EPackage metamodel) {
        if (eStructuralFeature instanceof EAttribute) {
            EAttribute eAttribute = (EAttribute) eStructuralFeature;
            EAttribute compositeEAttribute = (EAttribute) findCompositeEAttribute(eAttribute, coverage);
            if (compositeEAttribute != null) {
                if (eStructuralFeature.getUpperBound() == -1) {
                    EList<Object> set = (EList<Object>) compositeResult.eGet(compositeEAttribute);
                    set.add(digestValue(value));
                } else {
                    compositeResult.eSet(compositeEAttribute, digestValue(value));
                }
            }
        } else if (eStructuralFeature instanceof EReference) {
            EReference eReference = (EReference) eStructuralFeature;
            EReference compositeEReference = findCompositeEReference(eReference, coverage);
            if (value.isJsonObject()) {
                JsonObject childJsonObject = value.getAsJsonObject();
                String childClassName = eReference.getEType().getName();
                EClassifier eChildClassifier = metamodel.getEClassifier(childClassName);
                if (eChildClassifier != null) {
                    EClass compositeEClass = (EClass) findCompositeEClass((EClass) eChildClassifier, coverage);
                    if (compositeEClass != null) {
                        EObject child = instantiateEClassifier(eChildClassifier, childJsonObject, compositeEClass,
                                coverage, metamodel);
                        if (compositeEReference.getUpperBound() == -1) {
                            EList<Object> set = (EList<Object>) compositeResult.eGet(compositeEReference);
                            set.add(child);
                        } else {
                            compositeResult.eSet(compositeEReference, child);
                        }
                    }
                }
            }
        }
    }

    private EClass findCompositeEClass(EClass object, Coverage coverage) {
        for (CoverageMapping mapping : coverage.getMappings()) {
            if (mapping instanceof ConceptMapping) {
                ConceptMapping conceptMapping = (ConceptMapping) mapping;
                if (conceptMapping.getSource().getName().equals(object.getName()))
                    return conceptMapping.getTarget();
            }
        }
        return null;
    }

    private EAttribute findCompositeEAttribute(EAttribute object, Coverage coverage) {
        for (CoverageMapping mapping : coverage.getMappings()) {
            if (mapping instanceof AttMapping) {
                AttMapping attMapping = (AttMapping) mapping;
                if (attMapping.getSource().getName().equals(object.getName()))
                    return attMapping.getTarget();
            }
        }
        return null;
    }

    private EReference findCompositeEReference(EReference object, Coverage coverage) {
        for (CoverageMapping mapping : coverage.getMappings()) {
            if (mapping instanceof RefMapping) {
                RefMapping refMapping = (RefMapping) mapping;
                if (refMapping.getSource().getName().equals(object.getName()))
                    return refMapping.getTarget();
            }
        }
        return null;
    }

    protected Object digestValue(JsonElement value) {
        if (value.isJsonPrimitive() && value.getAsJsonPrimitive().isString()) {
            return value.getAsJsonPrimitive().getAsString();
        } else if (value.isJsonPrimitive() && value.getAsJsonPrimitive().isNumber()) {
            return new Integer(value.getAsJsonPrimitive().getAsNumber().intValue());
        } else if (value.isJsonPrimitive() && value.getAsJsonPrimitive().isBoolean()) {
            return value.getAsJsonPrimitive().getAsBoolean() ? Boolean.TRUE : Boolean.FALSE;
        } else {
            return null;
        }
    }

    protected void saveModel(File targetFile, List<EObject> eObjects) {
        ResourceSet rset = new ResourceSetImpl();
        Resource res = rset.createResource(URI.createFileURI(targetFile.getAbsolutePath()));

        try {
            for (EObject eObject : eObjects) {
                res.getContents().add(eObject);
            }
            res.save(null);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}