org.apromore.plugin.portal.compareBP.ComparePlugin.java Source code

Java tutorial

Introduction

Here is the source code for org.apromore.plugin.portal.compareBP.ComparePlugin.java

Source

/*
 * Copyright  2009-2016 The Apromore Initiative.
 *
 * This file is part of "Apromore".
 *
 * "Apromore" is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * "Apromore" is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program.
 * If not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
 */

package org.apromore.plugin.portal.compareBP;

// Java 2 Standard Edition packages
import java.io.ByteArrayInputStream;
import java.util.*;

import ee.ut.eventstr.comparison.differences.ModelAbstractions;
import hub.top.petrinet.PetriNet;
import hub.top.petrinet.Place;
import hub.top.petrinet.Transition;
import org.apache.commons.io.IOUtils;

// Java 2 Enterprise Edition packages
import javax.inject.Inject;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

// Third party packages
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.math3.analysis.function.Exp;
import org.apromore.canoniser.Canoniser;
import org.apromore.helper.Version;
import org.apromore.model.ExportFormatResultType;
import org.apromore.model.ProcessSummaryType;
import org.apromore.model.SummaryType;
import org.apromore.model.LogSummaryType;
import org.apromore.model.VersionSummaryType;
import org.apromore.plugin.property.PluginParameterType;
import org.apromore.plugin.property.RequestParameterType;
import org.apromore.portal.context.PluginPortalContext;
import org.apromore.portal.dialogController.MainController;
import org.apromore.service.compare.CompareService;
import org.deckfour.xes.model.XLog;
import org.jbpt.petri.Flow;
import org.jbpt.petri.NetSystem;
import org.jbpt.hypergraph.abs.Vertex;
import org.jbpt.petri.io.PNMLSerializer;
import org.processmining.exporting.bpmn.BPMNExport;
import org.processmining.models.graphbased.directed.petrinet.Petrinet;
import org.processmining.plugins.bpmn.converter.BPMNConverter;
import org.processmining.plugins.bpmn.converter.PetriNetToBPMNConverterPlugin;
import org.semanticweb.kaon2.jb;
import org.semanticweb.kaon2.lo;
import org.springframework.stereotype.Component;

// Local packages
import org.apromore.plugin.portal.DefaultPortalPlugin;
import org.apromore.plugin.portal.PortalContext;
import org.apromore.service.CanoniserService;
import org.apromore.service.DomainService;
import org.apromore.service.ProcessService;
import org.apromore.service.EventLogService;
import org.apromore.service.helper.UserInterfaceHelper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.processmining.models.graphbased.directed.bpmn.BPMNDiagram;
import org.zkoss.zul.Messagebox;

/**
 * A user interface to the BPMN miner service.
 */
@Component("plugin")
public class ComparePlugin extends DefaultPortalPlugin {
    private final CompareService compareService;
    private final ProcessService processService;
    private final CanoniserService canoniserService;
    private final EventLogService eventLogService;
    private Map<ProcessSummaryType, List<VersionSummaryType>> processVersions;

    private String label = "Compare";
    private String groupLabel = "Analyze";

    private static final Logger LOGGER = LoggerFactory.getLogger(ComparePlugin.class.getCanonicalName());

    @Inject
    public ComparePlugin(final CompareService compareService, final ProcessService processService,
            final CanoniserService canoniserService, final EventLogService eventLogService) {
        this.compareService = compareService;
        this.processService = processService;
        this.canoniserService = canoniserService;
        this.eventLogService = eventLogService;
    }

    @Override
    public String getLabel(Locale locale) {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }

    @Override
    public String getGroupLabel(Locale locale) {
        return groupLabel;
    }

    public void setGroupLabel(String groupLabel) {
        this.groupLabel = groupLabel;
    }

    public PetriNet getNet(ProcessSummaryType process, VersionSummaryType vst, PortalContext context,
            HashSet<String> labels) throws Exception {
        int procID = process.getId();
        String procName = process.getName();
        String branch = vst.getName();
        Version version = new Version(vst.getVersionNumber());
        String username = context.getCurrentUser().getUsername();
        int folderId = context.getCurrentFolder() == null ? 0 : context.getCurrentFolder().getId();

        Set<RequestParameterType<?>> requestProperties = new HashSet<>();
        requestProperties.add(new RequestParameterType<>("isCpfTaskPnmlTransition", true));
        requestProperties.add(new RequestParameterType<>("isCpfTaskPnmlTrans", false));

        ExportFormatResultType data = processService.exportProcess(procName, procID, branch, version, "PNML 1.3.2",
                "MN", false, requestProperties);
        byte[] bytes = IOUtils.toByteArray(data.getNative().getInputStream());
        PNMLSerializer pnmlSerializer = new PNMLSerializer();

        NetSystem net = pnmlSerializer.parse(bytes);

        for (org.jbpt.petri.Transition t : net.getObservableTransitions())
            if (t.getLabel().trim().length() > 0)
                labels.add(t.getLabel().trim());

        return jbptToUma(net);
    }

    @Override
    public void execute(PortalContext context) {
        LOGGER.info("Executing");

        Map<SummaryType, List<VersionSummaryType>> elements = context.getSelection()
                .getSelectedProcessModelVersions();
        Set<LogSummaryType> selectedLogSummaryType = new HashSet<>();
        Map<ProcessSummaryType, List<VersionSummaryType>> selectedProcessVersions = new HashMap<>();
        for (Map.Entry<SummaryType, List<VersionSummaryType>> entry : elements.entrySet()) {
            if (entry.getKey() instanceof LogSummaryType) {
                selectedLogSummaryType.add((LogSummaryType) entry.getKey());
            } else if (entry.getKey() instanceof ProcessSummaryType) {
                selectedProcessVersions.put((ProcessSummaryType) entry.getKey(), entry.getValue());
            }
        }

        //        if(selectedProcessVersions.size() != 1) {
        //            Messagebox.show("Please, select exactly one process.", "Wrong Process Selection", Messagebox.OK, Messagebox.INFORMATION);
        //            return;
        //        }

        // Populate "details" with the process:version selections
        List<ProcessSummaryType> procS = new ArrayList<>();
        List<VersionSummaryType> verS = new ArrayList<>();
        List<PetriNet> nets = new ArrayList<>();
        List<HashSet<String>> observable = new ArrayList<>();

        try {
            for (ProcessSummaryType processSummary : selectedProcessVersions.keySet()) {
                List<VersionSummaryType> versionSummaries = selectedProcessVersions.get(processSummary);
                if (versionSummaries.isEmpty()) {
                    List<VersionSummaryType> x = processSummary.getVersionSummaries();
                    versionSummaries.add(x.get(x.size() - 1)); // default to the head version
                }
                for (VersionSummaryType versionSummary : versionSummaries) {
                    procS.add(processSummary);
                    verS.add(versionSummary);
                    HashSet<String> obs = new HashSet<>();
                    nets.add(getNet(processSummary, versionSummary, context, obs));
                    observable.add(new HashSet<String>(obs));
                }
            }

            List<XLog> logs = new ArrayList<>();
            for (LogSummaryType logType : selectedLogSummaryType) {
                logs.add(eventLogService.getXLog(logType.getId()));
            }

            CompareController controller = new CompareController(context, compareService, eventLogService);

            if (logs.size() == 2) {
                controller.compareLL(logs.get(0), logs.get(1));
                return;
            } else if (logs.size() == 1 && selectedProcessVersions.size() == 1) {
                controller.compareML(nets.get(0), observable.get(0), logs.get(0));
                return;
            } else if (selectedProcessVersions.size() == 2) {
                context.getMessageHandler().displayInfo("Performing comparison.");

                ModelAbstractions model1 = toModelAbstractions(procS.get(0), verS.get(0));
                ModelAbstractions model2 = toModelAbstractions(procS.get(1), verS.get(1));

                controller.compareMM(model1, model2, observable.get(0), observable.get(1), procS.get(0),
                        verS.get(0), procS.get(1), verS.get(1));
                context.getMessageHandler().displayInfo("Performed comparison.");
                return;
            } else if (logs.size() > 2 || selectedProcessVersions.size() > 2) {
                context.getMessageHandler().displayInfo("There are " + selectedProcessVersions.size()
                        + " process versions selected, but only 2 can be compared at a time.");
                return;
            }

            // Select the comparison method according to the elements selected in Apromore and input data
            Iterator<List<VersionSummaryType>> selectedVersions = selectedProcessVersions.values().iterator();

            // At least 1 process versions must be selected. Not necessarily of different processes
            if ((selectedProcessVersions.size() == 1 && selectedVersions.next().size() < 1)
                    || selectedProcessVersions.size() < 1) {
                controller.compareLLPopup();
                context.getMessageHandler().displayInfo("Log to log comparison.");
                return;
            }

            switch (selectedProcessVersions.size()) {
            case 1:
                controller.compareMLPopup(nets.get(0), observable.get(0));
                context.getMessageHandler().displayInfo("Performed conformance checker.");
                break;
            default:
                context.getMessageHandler()
                        .displayInfo("Comparison method not found. Check the selected elements.");
            }

            /*try {
                // Populate "details" with the process:version selections
                List<ProcessSummaryType> procS = new ArrayList<>();
                List<VersionSummaryType> verS = new ArrayList<>();
                List<PetriNet> nets = new ArrayList<>();
                List<HashSet<String>> observable = new ArrayList<>();
                for (ProcessSummaryType processSummary: selectedProcessVersions.keySet()) {
            List<VersionSummaryType> versionSummaries = selectedProcessVersions.get(processSummary);
            if (versionSummaries.isEmpty()) {
                List<VersionSummaryType> x = processSummary.getVersionSummaries();
                versionSummaries.add(x.get(x.size() - 1));  // default to the head version
            }
            for (VersionSummaryType versionSummary: versionSummaries) {
                procS.add(processSummary);
                verS.add(versionSummary);
                HashSet<String> obs = new HashSet<>();
                nets.add(getNet(processSummary, versionSummary, context, obs));
                observable.add(new HashSet<String>(obs));
            }
                }
                
                // If we have exactly two process:version selections, perform the comparison
                switch (selectedProcessVersions.size()) {
                case 1:
            new CompareController(context, compareService, nets.get(0), observable.get(0));
            context.getMessageHandler().displayInfo("Performed conformance checker.");
            break;
                case 2:
            context.getMessageHandler().displayInfo("Performing comparison.");
                
            ModelAbstractions model1 = toModelAbstractions(procS.get(0), verS.get(0));
            ModelAbstractions model2 = toModelAbstractions(procS.get(1), verS.get(1));
                
            new CompareController(context,compareService, model1, model2, observable.get(0), observable.get(1), procS.get(0), verS.get(0), procS.get(1), verS.get(1));
            context.getMessageHandler().displayInfo("Performed comparison.");
            break;
                default:
            context.getMessageHandler().displayInfo("There are " + selectedProcessVersions.size() + " process versions selected, but only 2 can be compared at a time.");
                }
            }catch(Exception e){
                e.printStackTrace();
            }*/

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private ModelAbstractions toModelAbstractions(ProcessSummaryType process, VersionSummaryType version)
            throws Exception {
        ExportFormatResultType result = processService.exportProcess(process.getName(), // process name
                process.getId(), // process ID
                version.getName(), // branch
                new Version(version.getVersionNumber()), // version number,
                "BPMN 2.0", // nativeType,
                null, // annotation name,
                false, // with annotations?
                Collections.EMPTY_SET // canoniser properties
        );
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        TransformerFactory.newInstance().newTransformer()
                .transform(new StreamSource(result.getNative().getInputStream()), new StreamResult(baos));
        return new ModelAbstractions(baos.toByteArray());
    }

    //    public PetriNet getNet(int model, PortalContext context, HashSet<String> labels, ProcessSummaryType process ) throws Exception{
    ////        processVersions = context.getSelection().getSelectedProcessModelVersions();
    ////
    ////        for (ProcessSummaryType process : processVersions.keySet()) {
    ////            i++;
    ////
    ////            System.out.println("enter to the net extraction! = "+i +" -- "+ model);
    ////            for (VersionSummaryType vst : processVersions.get(process)) {
    //                System.out.println("1");
    //                int procID = process.getId();
    //                String procName = process.getName();
    //                String branch = vst.getName();
    //                Version version = new Version(vst.getVersionNumber());
    //                String username = context.getCurrentUser().getUsername();
    //                int folderId = context.getCurrentFolder() == null ? 0 : context.getCurrentFolder().getId();
    //
    //                System.out.println("2");
    //
    //                Set<RequestParameterType<?>> requestProperties = new HashSet<>();
    //                requestProperties.add(new RequestParameterType<>("isCpfTaskPnmlTransition",true));
    //                requestProperties.add(new RequestParameterType<>("isCpfTaskPnmlTrans",false));
    //
    //                System.out.println("3");
    //
    //                ExportFormatResultType data = processService.exportProcess(procName, procID, branch, version, "PNML 1.3.2", "MN", false, requestProperties);
    //                byte[] bytes = IOUtils.toByteArray(data.getNative().getInputStream());
    //                PNMLSerializer pnmlSerializer = new PNMLSerializer();
    //
    //                System.out.println("4");
    //
    //                NetSystem net = pnmlSerializer.parse(bytes);
    //
    //                System.out.println("5");
    //                for(org.jbpt.petri.Transition t : net.getSilentTransitions())
    //                    labels.add(t.getName());
    //
    //                System.out.println("6");
    ////                if(i == model)
    //                    return jbptToUma(net);
    //                //new CompareController(context, compareService, jbptToUma(net));
    ////            }
    ////        }
    ////
    ////        return null;
    //    }

    public PetriNet jbptToUma(NetSystem net) {
        PetriNet copy = new PetriNet();
        Map<Vertex, Place> places = new HashMap<>();
        Map<Vertex, Transition> transitions = new HashMap<>();

        int index = 0;

        for (org.jbpt.petri.Place place : net.getPlaces()) {
            Place newPlace = copy.addPlace("p" + index++);
            places.put(place, newPlace);
        }

        for (org.jbpt.petri.Transition trans : net.getTransitions()) {
            String name = trans.getLabel() == null || trans.getLabel().isEmpty() ? "t" + index++ : trans.getLabel();
            Transition newTrans = copy.addTransition(name);
            transitions.put(trans, newTrans);
        }

        for (Flow flow : net.getFlow()) {
            if (flow.getSource() instanceof org.jbpt.petri.Place)
                copy.addArc(places.get(flow.getSource()), transitions.get(flow.getTarget()));
            else
                copy.addArc(transitions.get(flow.getSource()), places.get(flow.getTarget()));
        }

        for (org.jbpt.petri.Place place : net.getSourcePlaces())
            places.get(place).setTokens(1);

        return copy;
    }

}