// Copyright 2012 Georg-August-Universität Göttingen, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package de.ugoe.cs.autoquest.commands.sequences;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.logging.Level;
import de.ugoe.cs.autoquest.CommandHelpers;
import de.ugoe.cs.autoquest.SequenceInstanceOf;
import de.ugoe.cs.autoquest.eventcore.Event;
import de.ugoe.cs.util.console.Command;
import de.ugoe.cs.util.console.Console;
import de.ugoe.cs.util.console.GlobalDataContainer;
/**
*
* Command to check all sequences of a collection of sequences for correct timestamps and event
* order. It supports counting the number of invalid sequences, listing details about invalid
* sequences and timestamps, as well as deleting invalid sequences.
*
*
* @author Patrick Harms
* @version 1.0
*/
public class CMDcheckEventTimestamps implements Command {
/*
* (non-Javadoc)
*
* @see de.ugoe.cs.util.console.Command#run(java.util.List)
*/
@SuppressWarnings("unchecked")
@Override
public void run(List parameters) {
String command;
String sequencesName;
String newSequencesName;
try {
command = (String) parameters.get(0);
sequencesName = (String) parameters.get(1);
if (parameters.size() > 2) {
newSequencesName = (String) parameters.get(2);
}
else {
newSequencesName = sequencesName;
}
}
catch (Exception e) {
throw new IllegalArgumentException("must provide a command and a sequences name");
}
Collection> sequences = null;
Object dataObject = GlobalDataContainer.getInstance().getData(sequencesName);
if (dataObject == null) {
CommandHelpers.objectNotFoundMessage(sequencesName);
return;
}
if (!SequenceInstanceOf.isCollectionOfSequences(dataObject)) {
CommandHelpers.objectNotType(sequencesName, "Collection>>");
return;
}
sequences = (Collection>) dataObject;
if ("count".equals(command)) {
countSequencesWithInvalidTimestamps(sequences);
}
else if ("list".equals(command)) {
listSequencesWithInvalidTimestamps(sequences);
Console.println("sequences with timestamp issues listed");
}
else if ("sort".equals(command)) {
sortEventsUsingTimestamps(sequences, newSequencesName);
}
else if ("delete".equals(command)) {
deleteSequencesWithInvalidTimestamps(sequences, newSequencesName);
}
}
/**
*
* counts the number of invalid sequences in the provided collections of invalid sequences
*
*
* @param sequences collection of sequences to check for invalid ones
*/
private void countSequencesWithInvalidTimestamps(Collection> sequences) {
int sequenceCount = 0;
for (List sequence : sequences) {
Event previous = null;
for (int i = 0; i < sequence.size(); i++) {
Event currentEvent = sequence.get(i);
if ((previous != null) && (previous.getTimestamp() > currentEvent.getTimestamp())) {
sequenceCount++;
break;
}
previous = currentEvent;
}
}
if (sequenceCount == 0) {
Console.println("no sequences have issues");
}
else {
Console.traceln(Level.WARNING, sequenceCount + " sequences have timestamp issues");
}
}
/**
*
* lists details about invalid timestamp orders of events in the provided collection of
* sequences
*
*
* @param sequences the collection of sequences to check
*/
private void listSequencesWithInvalidTimestamps(Collection> sequences) {
int sequenceCount = 0;
for (List sequence : sequences) {
sequenceCount++;
Event previous = null;
List issues = new LinkedList();
for (int i = 0; i < sequence.size(); i++) {
Event currentEvent = sequence.get(i);
if ((previous != null) && (previous.getTimestamp() > currentEvent.getTimestamp())) {
issues.add(currentEvent + " has an earlier timestamp than the preceeding " +
previous);
}
previous = currentEvent;
}
if (issues.size() > 0) {
Console.traceln(Level.WARNING, "sequence " + sequenceCount +
" has the following issues:");
for (String issue : issues) {
Console.traceln(Level.WARNING, " " + issue);
}
}
}
}
/**
*
* sorts events in sequences with invalid timestamps from the provided collection of sequences and
* stores them under new name
*
*
* @param sequences the collection of sequences to sort the events in
* @param newSequencesName the name for the new corrected collection of sequences
*/
private void sortEventsUsingTimestamps(Collection> sequences,
String newSequencesName)
{
Collection> newSequences = new LinkedList>();
for (List sequence : sequences) {
List newSequence = new LinkedList<>();
for (Event currentEvent : sequence) {
boolean added = false;
ListIterator iterator = newSequence.listIterator();
while (iterator.hasNext()) {
if (iterator.next().getTimestamp() > currentEvent.getTimestamp()) {
iterator.previous();
iterator.add(currentEvent);
added = true;
break;
};
}
if (!added) {
newSequence.add(currentEvent);
}
}
newSequences.add(newSequence);
}
Console.traceln(Level.WARNING, sequences.size() +
" sequences sorted based on event timestamps");
if (GlobalDataContainer.getInstance().addData(newSequencesName, newSequences)) {
CommandHelpers.dataOverwritten(newSequencesName);
}
}
/**
*
* deletes sequences with invalid timestamps from the provided collection of sequences and
* stores them under new name
*
*
* @param sequences the collection of sequences to check for invalid sequences
* @param newSequencesName the name for the new corrected collection of sequences
*/
private void deleteSequencesWithInvalidTimestamps(Collection> sequences,
String newSequencesName)
{
Collection> newSequences = new LinkedList>();
for (List sequence : sequences) {
Event previous = null;
boolean allFine = true;
for (int i = 0; i < sequence.size(); i++) {
Event currentEvent = sequence.get(i);
if ((previous != null) && (previous.getTimestamp() > currentEvent.getTimestamp())) {
allFine = false;
break;
}
previous = currentEvent;
}
if (allFine) {
newSequences.add(sequence);
}
}
if (newSequences.size() == sequences.size()) {
Console.println("no sequences with issues deleted");
}
else {
Console.traceln(Level.WARNING, (sequences.size() - newSequences.size()) +
" sequences with timestamp issues deleted");
if (GlobalDataContainer.getInstance().addData(newSequencesName, newSequences)) {
CommandHelpers.dataOverwritten(newSequencesName);
}
}
}
/*
* (non-Javadoc)
*
* @see de.ugoe.cs.util.console.Command#help()
*/
@Override
public String help() {
return "checkEventTimestamps {}";
}
}