fr.inria.atlanmod.emf.graphs.Connectedness.java Source code

Java tutorial

Introduction

Here is the source code for fr.inria.atlanmod.emf.graphs.Connectedness.java

Source

/*******************************************************************************
 * Copyright (c) 2015 Abel Gmez.
 * 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:
 *     Abel Gmez - initial API and implementation
 ******************************************************************************/
package fr.inria.atlanmod.emf.graphs;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EPackage.Registry;
import org.eclipse.emf.ecore.EReference;
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.impl.XMIResourceFactoryImpl;

public class Connectedness {
    private static final Logger LOG = Logger.getLogger(Connectedness.class.getName());

    private static final String INPUT_METAMODEL = "m";
    private static final String INPUT_MODEL = "i";
    private static final String INPUT_METAMODEL_LONG = "metamodel";
    private static final String INPUT_MODEL_LONG = "input-model";
    private static final String LOG_UNREACHABLE = "u";
    private static final String LOG_UNREACHABLE_LONG = "log-unreachable";

    private static final String[] CANDIDATE_ECLASS_NAMES = { "IfcProject", "IfcBuilding",
            //      "IfcBuildingStorey",
            //      "IfcLocalPlacement",
            //      "IfcRelAggregates",
            //      "IfcRelContainedInSpatialStructure",
            //      "IfcSite",
            //      "IfcWall",
    };

    public static void main(String[] args) {

        Options options = createOptions();

        CommandLineParser parser = new PosixParser();

        try {
            CommandLine commandLine = parser.parse(options, args);
            String inputMetamodel = commandLine.getOptionValue(INPUT_METAMODEL);
            String inputModel = commandLine.getOptionValue(INPUT_MODEL);
            Boolean logUnreachable = commandLine.hasOption(LOG_UNREACHABLE);

            ResourceSet resourceSet = new ResourceSetImpl();
            Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap()
                    .put(Resource.Factory.Registry.DEFAULT_EXTENSION, new XMIResourceFactoryImpl());

            {
                LOG.log(Level.INFO, "Loading input metamodel");
                URI uri = URI.createFileURI(inputMetamodel);
                Resource resource = resourceSet.getResource(uri, true);
                registerEPackages(resource);
            }

            URI uri = URI.createFileURI(inputModel);

            LOG.log(Level.INFO, "Loading input model");
            Resource resource = resourceSet.getResource(uri, true);

            LOG.log(Level.INFO, "Getting input model contents");
            Set<EObject> resourceContents = getResourceContents(resource);
            int totalCount = resourceContents.size();

            LOG.log(Level.INFO, MessageFormat.format("Input model contains {0} elements", totalCount));

            List<EClassifier> candidateEClassifiers = buildCandidateEClassifiers();

            for (Iterator<EObject> it = resource.getAllContents(); it.hasNext();) {
                EObject eObject = it.next();
                if (candidateEClassifiers.contains(eObject.eClass())) {
                    Set<EObject> reachableEObjects = getReachableEObjects(eObject);
                    int i = reachableEObjects.size();
                    LOG.log(Level.INFO, MessageFormat.format("Found {0} reachable objects from {1} (EClass {2})", i,
                            EcoreUtil.getURI(eObject), eObject.eClass().getName()));
                    if (logUnreachable) {
                        Set<EObject> unreachableEObjects = new HashSet<>(resourceContents);
                        unreachableEObjects.removeAll(reachableEObjects);
                        LOG.log(Level.INFO,
                                MessageFormat.format("{0} elements are unreachable from {1} (EClass {2})",
                                        unreachableEObjects.size(), EcoreUtil.getURI(eObject),
                                        eObject.eClass().getName()));
                        for (EObject unreachableEObject : unreachableEObjects) {
                            LOG.log(Level.INFO, MessageFormat.format("Unreachable EObject {0} is of type {1}",
                                    EcoreUtil.getURI(unreachableEObject), unreachableEObject.eClass()));
                        }
                    }
                }
            }

        } catch (ParseException e) {
            LOG.log(Level.SEVERE, e.getLocalizedMessage(), e);
            LOG.log(Level.INFO, "Current arguments: " + Arrays.toString(args));
            HelpFormatter formatter = new HelpFormatter();
            formatter.printHelp("java -jar <this-file.jar>", options, true);
        } catch (Throwable e) {
            LOG.log(Level.SEVERE, e.getLocalizedMessage(), e);
            MessageUtil.showError(e.toString());
        }
    }

    /**
     * Builds the list of candidate {@link EClassifier}s, i.e., returns a
     * {@link List} of the {@link EClassifier}s in the whole {@link EPackage}
     * {@link Registry} whose names match <code>CANDIDATE_ECLASS_NAMES</code>
     * 
     * @return The list of candidate {@link EClassifier}s
     */
    protected static List<EClassifier> buildCandidateEClassifiers() {
        List<EClassifier> candidateEClassifiers = new ArrayList<>();
        for (String eClassName : CANDIDATE_ECLASS_NAMES) {
            for (Object obj : EPackage.Registry.INSTANCE.values()) {
                if (obj instanceof EPackage) {
                    EPackage ePackage = (EPackage) obj;
                    candidateEClassifiers.add(ePackage.getEClassifier(eClassName));
                }
            }
        }
        return candidateEClassifiers;
    }

    /**
     * Returns the {@link Set} of {@link EObject}s that can be reached by
     * navigating {@link EReference}s, starting from <code>initialEObject</code>
     * 
     * @param initialEObject
     *            The initial {@link EObject}
     * @return The {@link Set} of reachable {@link EObject}s
     */
    private static Set<EObject> getReachableEObjects(EObject initialEObject) {
        Set<EObject> visited = new HashSet<>();
        Queue<EObject> next = new LinkedList<EObject>();
        next.add(initialEObject);

        while (!next.isEmpty()) {
            EObject activeEObject = next.poll();
            if (visited.add(activeEObject)) {
                next.addAll(activeEObject.eContents());
                next.addAll(activeEObject.eCrossReferences());
            }
        }

        return visited;
    }

    protected static Set<EObject> getResourceContents(Resource resource) {
        Set<EObject> visited = new HashSet<>();
        for (Iterator<EObject> it = resource.getAllContents(); it.hasNext(); visited.add(it.next()))
            ;
        return visited;
    }

    /**
     * Registers in the global {@link Registry} all the {@link EPackage}s
     * contained in the given {@link Resource}
     * 
     * @param resource
     */
    private static void registerEPackages(Resource resource) {
        for (Iterator<EObject> it = resource.getAllContents(); it.hasNext();) {
            EObject eObject = it.next();
            if (eObject instanceof EPackage) {
                EPackage ePackage = (EPackage) eObject;
                EPackage.Registry.INSTANCE.put(ePackage.getNsURI(), ePackage);
            }
        }
    }

    /**
     * Creates the program options
     * 
     * @param options
     * @return
     */
    private static Options createOptions() {

        Options options = new Options();

        Option inputMetamodelOpt = OptionBuilder.create(INPUT_METAMODEL);
        inputMetamodelOpt.setLongOpt(INPUT_METAMODEL_LONG);
        inputMetamodelOpt.setArgName("source.ecore");
        inputMetamodelOpt.setDescription("Path of the source metamodel file");
        inputMetamodelOpt.setArgs(1);
        inputMetamodelOpt.setRequired(true);

        Option inputModelOpt = OptionBuilder.create(INPUT_MODEL);
        inputModelOpt.setLongOpt(INPUT_MODEL_LONG);
        inputModelOpt.setArgName("input.xmi");
        inputModelOpt.setDescription("Path of the input file");
        inputModelOpt.setArgs(1);
        inputModelOpt.setRequired(true);

        Option logUnreachableOpt = OptionBuilder.create(LOG_UNREACHABLE);
        logUnreachableOpt.setLongOpt(LOG_UNREACHABLE_LONG);
        logUnreachableOpt.setDescription("Log information about unreachable objects");
        logUnreachableOpt.setArgs(0);
        logUnreachableOpt.setRequired(false);

        options.addOption(inputMetamodelOpt);
        options.addOption(inputModelOpt);
        options.addOption(logUnreachableOpt);

        return options;
    }

}