/** @param args */
  public static void main(String[] args) {
    XFactoryBufferedImpl factory = new XFactoryBufferedImpl();

    XLog log = factory.createLog();
    XTrace trace = factory.createTrace();
    XEvent event1 = factory.createEvent();
    XEvent event2 = factory.createEvent();
    XEvent event3 = (XEvent) event2.clone();

    System.out.println("Event 3 and event 2 are equal: " + event3.equals(event2));

    trace.add(event1);
    trace.add(event2);
    log.add(trace);

    XLog log2 = (XLog) log.clone();

    System.out.println("Log 1 and log 2 are equal: " + log.equals(log2));

    trace.remove(event1);

    System.out.println("This log should start with 1 events");
    doTest(log);

    System.out.println("This log should start with 2 event");
    doTest(log2);
  }
  @PluginVariant(requiredParameterLabels = {0})
  public JComponent visualize(final PluginContext context, final XLog log) {
    JPanel panel = new JPanel(new BorderLayout());
    JLabel lbInfo = new JLabel();
    lbInfo.setText(
        "Log " + log.getAttributes().get("concept:name") + " has " + log.size() + " traces ");

    JTable tbTraces = new JTable(new XTraceTableModel(log));
    panel.add(lbInfo, BorderLayout.NORTH);
    panel.add(new JScrollPane(tbTraces), BorderLayout.CENTER);
    return panel;
  }
 private static void toString(XLog log) {
   System.out.println("---------------------------------------");
   System.out.println("" + log.hashCode());
   for (XTrace trace : log) {
     System.out.println("  |-" + trace.hashCode());
     for (XEvent event : trace) {
       System.out.println("    |-" + event.hashCode());
     }
   }
 }
 @Override
 public Object getValueAt(int rowIndex, int columnIndex) {
   switch (columnIndex) {
     case 0:
       return rowIndex + 1;
     case 1:
       XTrace trace = log.get(rowIndex);
       return convertTraceToSeq(trace);
   }
   return "";
 }
  private XLog[] createdXFolds() {

    if (log.size() < fold) fold = log.size();
    XLog[] logs = new XLog[fold];

    for (int i = 0; i < fold; i++) {
      logs[i] = factory.createLog(log.getAttributes());
    }

    if (log.size() == fold) {
      int pos = 0;
      for (XTrace t : log) {
        logs[pos].add(t);
        pos++;
      }
    } else {
      boolean finish = false;
      while (!finish) {
        finish = true;
        for (XTrace t : log) {
          int pos = r.nextInt(fold);
          logs[pos].add(t);
        }
        for (int i = 0; i < logs.length; i++) {
          if (logs[i].size() == 0) {
            finish = false;
          }
        }
        if (!finish) {
          for (int i = 0; i < fold; i++) {
            logs[i].clear();
          }
        }
      }
    }

    return logs;
  }
  @Override
  public Measure computeMeasurement(
      UIPluginContext pluginContext,
      XEventClassifier xEventClassifier,
      PetrinetWithMarking petrinetWithMarking,
      MiningAlgorithm miningAlgorithm,
      XLog log) {
    Measure measure = new Measure();
    double fitness = 0.0;
    this.log = log;
    XLog[] logs = createdXFolds();

    AlignmentBasedFitness alignmentBasedFitness = new AlignmentBasedFitness();

    for (int i = 0; i < fold; i++) {
      XLog log1 = factory.createLog(log.getAttributes());
      for (int j = 0; j < fold; j++) {
        if (j != i) {
          log1.addAll(logs[j]);
        }
      }

      try {
        petrinetWithMarking = miningAlgorithm.minePetrinet(pluginContext, log1, false);
        Double f =
            alignmentBasedFitness
                .computeMeasurement(
                    pluginContext, xEventClassifier, petrinetWithMarking, miningAlgorithm, logs[i])
                .getValue();
        fitness += (f != null) ? f : 0.0;
      } catch (Exception e) {
        return measure;
      }
    }

    measure.setValue(fitness / (double) fold);
    return measure;
  }
  @Plugin(
      name = "Add End Artificial Events",
      parameterLabels = {"Log"},
      returnLabels = {"Altered log"},
      returnTypes = {XLog.class},
      userAccessible = true,
      help = "Adds an artificial  end task to every trace in the log file")
  @UITopiaVariant(
      affiliation = "Department of Computer Science University of Pisa",
      author = "R.Guanciale,G.Spagnolo et al.",
      email = "*****@*****.**",
      pack = "PetriNetReplayAnalysis")
  public XLog addEvents(PluginContext context, XLog oldLog) {

    context.getFutureResult(0).setLabel(XConceptExtension.instance().extractName(oldLog));

    context.getProgress().setMinimum(0);
    context.getProgress().setMaximum(oldLog.size());
    context.getProgress().setIndeterminate(false);
    context.getProgress().setValue(0);

    XAttributeMap logattlist = copyAttMap(oldLog.getAttributes());
    XLog newLog = new XLogImpl(logattlist);
    for (int i = 0; i < oldLog.size(); i++) {
      XTrace oldTrace = oldLog.get(i);
      XTrace newTrace = new XTraceImpl(copyAttMap(oldTrace.getAttributes()));
      for (int j = 0; j < oldTrace.size(); j++) {
        XEvent oldEvent = oldTrace.get(j);
        XEvent newEvent = new XEventImpl(copyAttMap(oldEvent.getAttributes()));
        newTrace.add(newEvent);
      }

      Date time = new Date();
      try {
        time =
            ((XAttributeTimestampImpl)
                    oldTrace.get(oldTrace.size() - 1).getAttributes().get("time:timestamp"))
                .getValue();
        time.setTime(time.getTime() + 1);
      } catch (Exception ex) {
      }

      newTrace.add(makeEvent("ArtificialEnd", time));

      newLog.add(newTrace);
      context.getProgress().inc();
    }
    return newLog;
  }
 @Override
 public int getRowCount() {
   return log.size();
 }
  @PluginVariant(
      requiredParameterLabels = {0, 1, 2, 3},
      variantLabel = "PerformanceDetailsSettingsWithMarking")
  // @Plugin(name = "PerformanceDetailsSettingsWithMarking", returnLabels = { "Performance Total" },
  // returnTypes = { TotalPerformanceResult.class }, parameterLabels = {}, userAccessible = true)
  // @UITopiaVariant(affiliation = "Department of Computer Science University of Pisa", author =
  // "R.Guanciale,G.Spagnolo et al.", email = "*****@*****.**", pack =
  // "PetriNetReplayAnalysis")
  public TotalPerformanceResult getPerformanceDetails(
      PluginContext context,
      XLog log,
      Petrinet net,
      ReplayFitnessSetting setting,
      Marking marking,
      XEventClassifier classif) {

    TotalPerformanceResult performance = new TotalPerformanceResult();

    XEventClasses classes = getEventClasses(log, classif);
    if (map == null) {
      // Map<Transition, XEventClass>
      map = getMapping(classes, net);
    }

    context
        .getConnectionManager()
        .addConnection(new LogPetrinetConnectionImpl(log, classes, net, map));

    PetrinetSemantics semantics = PetrinetSemanticsFactory.regularPetrinetSemantics(Petrinet.class);

    Replayer<ReplayFitnessCost> replayer =
        new Replayer<ReplayFitnessCost>(
            context, net, semantics, map, ReplayFitnessCost.addOperator);

    int replayedTraces = 0;
    context.getProgress().setMinimum(0);
    context.getProgress().setMaximum(log.size());
    for (XTrace trace : log) {
      List<XEventClass> list = getList(trace, classes);
      try {
        System.out.println("Replay :" + replayedTraces);
        List<Transition> sequence;

        sequence = replayer.replayTrace(marking, list, setting);
        if (sequence != null) {
          sequence = sortHiddenTransection(net, sequence, map);
          String tracename = getTraceName(trace);
          updatePerformance(net, marking, sequence, semantics, trace, performance, map, tracename);
          replayedTraces++;
          context.getProgress().inc();
          System.out.println("Replayed");
        }

      } catch (Exception ex) {
        System.out.println("Failed");
        context.log("Replay of trace " + trace + " failed: " + ex.getMessage());
      }
    }

    context.log(
        "(based on a successful replay of "
            + replayedTraces
            + " out of "
            + log.size()
            + " traces)");

    ReplayAnalysisConnection connection = new ReplayAnalysisConnection(performance, log, net);
    context.getConnectionManager().addConnection(connection);

    return performance;
  }
  // Rupos public methos
  @PluginVariant(
      requiredParameterLabels = {0, 1},
      variantLabel = "PerformanceDetailsUI")
  // @Plugin(name = "PerformanceDetailsUI", returnLabels = { "Performance Total" }, returnTypes = {
  // TotalPerformanceResult.class }, parameterLabels = {}, userAccessible = true)
  @UITopiaVariant(
      affiliation = "Department of Computer Science University of Pisa",
      author = "R.Guanciale,G.Spagnolo et al.",
      email = "*****@*****.**",
      pack = "PetriNetReplayAnalysis")
  public TotalPerformanceResult getPerformanceDetails(
      UIPluginContext context, XLog log, Petrinet net) {

    // list possible classifiers
    List<XEventClassifier> classList = new ArrayList<XEventClassifier>(log.getClassifiers());
    // add default classifiers
    if (!classList.contains(XLogInfoImpl.RESOURCE_CLASSIFIER)) {
      classList.add(0, XLogInfoImpl.RESOURCE_CLASSIFIER);
    }
    //				if (!classList.contains(XLogInfoImpl.LIFECYCLE_TRANSITION_CLASSIFIER)){
    //					classList.add(0, XLogInfoImpl.LIFECYCLE_TRANSITION_CLASSIFIER);
    //				}
    if (!classList.contains(XLogInfoImpl.NAME_CLASSIFIER)) {
      classList.add(0, XLogInfoImpl.NAME_CLASSIFIER);
    }
    if (!classList.contains(XLogInfoImpl.STANDARD_CLASSIFIER)) {
      classList.add(0, XLogInfoImpl.STANDARD_CLASSIFIER);
    }

    Object[] availableEventClass = classList.toArray(new Object[classList.size()]);

    ReplayFitnessSetting setting = new ReplayFitnessSetting();
    suggestActions(setting, log, net);
    ReplayAnalysisUI ui = new ReplayAnalysisUI(setting);

    Marking marking;

    try {
      InitialMarkingConnection connection =
          context
              .getConnectionManager()
              .getFirstConnection(InitialMarkingConnection.class, context, net);
      marking = connection.getObjectWithRole(InitialMarkingConnection.MARKING);
    } catch (ConnectionCannotBeObtained ex) {
      context.log("Petri net lacks initial marking");
      context.getFutureResult(0).cancel(true);
      return null;
    }
    // Build and show the UI to make the mapping
    LogPetrinetAssUI mapping = new LogPetrinetAssUI(log, net, availableEventClass);
    // Create map or not according to the button pressed in the UI

    InteractionResult result = InteractionResult.NEXT;
    /*
     * The wizard loop.
     */
    boolean sem = true;
    /*
     * Show the current step.
     */
    int currentStep = 0;

    // TODO: Insert plugin description
    String label =
        "<html>"
            + "<h2>PetriNetReplayAnalysis: Performance metrics <br/></h2><p>"
            + "This package implement the algorithms described on this article<sup>1</sup>. <br/><br/>"
            + "This plugin replayed a log events on the bussiness process model. "
            + "The model is a Petri net and reproduces a bussiness process. "
            + "<br/>The result of performance plugin is a set Petri nets with annoted for all place sojourn,wait "
            + "and synchronization time for all trace log and all Petri net place,<br/> and annoted them on the Petri net. <br></p>"
            + "<br/><p>The user guide for this plugin is <a href=\"https://svn.win.tue.nl/repos/prom/Documentation/\">here "
            + "</a>https://svn.win.tue.nl/repos/prom/Documentation/PetriNetReplayAnalysis.pdf</p>"
            + "<br/><p>The code for this plugin is <a href=\"https://github.com/rupos-it/PetriNetReplayAnalysis\">"
            + "here </a>https://github.com/rupos-it/PetriNetReplayAnalysis</p>"
            + "<p><span style=\"font-size:8px;\"><sup>1</sup>Roberto Bruni, AndreaCorradini, Gianluigi Ferrari, "
            + "Tito Flagella, Roberto Guanciale, and Giorgio O. Spagnolo. Applying process analysis to the italian "
            + "egovernment enterprise architecture. <br/>In <i>Proceedings of WS-FM 2011,8th International Workshop on "
            + "Web Services and Formal Methods</i> <ahref=\"http://goo.gl/EmiDJ\">http://goo.gl/EmiDJ</a></span></p>"
            + " </html>";

    JComponent intro = new PanelIntroPlugin(label);
    JComponent config = ui.initComponents();
    result = context.showWizard("Select Type Mapping", true, false, intro);

    currentStep++;
    boolean d = false;
    while (sem) {

      switch (result) {
        case NEXT:
          /*
           * Show the next step.
           */

          if (currentStep == 0) {
            currentStep = 1;
          }
          if (currentStep == 1) {
            result = context.showWizard("Mapping Petrinet - Log", false, false, mapping);
            currentStep++;
            d = true;
            break;
          }
          if (currentStep == 2) {
            d = false;

            result = context.showWizard("Configure Performance Settings", false, true, config);
            ui.setWeights();
          }

          break;
        case PREV:
          /*
           * Move back.
           */
          if (d) {
            currentStep--;
            d = false;
          }
          if (currentStep == 1) {
            result = context.showWizard("Select Type Mapping", true, false, intro);
            // mapping = lpcfui=null;//.initComponents();
          }
          if (currentStep == 2) {
            result = context.showWizard("Mapping Petrinet - Log", false, false, mapping);
            currentStep--;
          }

          break;
        case FINISHED:
          /*
           * Return  final step.
           */
          map = getmap(mapping.getMap());
          sem = false;
          break;
        default:
          /*
           * Should not occur.
           */
          context.log("press Cancel");
          context.log("replay is not performed because not enough parameter is submitted");
          context.getFutureResult(0).cancel(true);
          return null;
      }
    }

    TotalPerformanceResult total =
        getPerformanceDetails(context, log, net, setting, marking, mapping.getSelectedClassifier());

    return total;
  }