Index: /trunk/quest-plugin-jfc/src/main/java/de/ugoe/cs/quest/plugin/jfc/JFCTraceCorrector.java
===================================================================
--- /trunk/quest-plugin-jfc/src/main/java/de/ugoe/cs/quest/plugin/jfc/JFCTraceCorrector.java	(revision 787)
+++ /trunk/quest-plugin-jfc/src/main/java/de/ugoe/cs/quest/plugin/jfc/JFCTraceCorrector.java	(revision 787)
@@ -0,0 +1,827 @@
+package de.ugoe.cs.quest.plugin.jfc;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * <p>
+ * corrects older JFC log files which sometimes do not contain correct source specification for
+ * events. It parses the file and adds component specifications to the source, that do not have
+ * them. The parent components are reused from the last GUI element the user worked with. The
+ * leaf component is parsed from the <code>toString</code> parameter that is provided with the
+ * source specifications. The resulting leaf nodes are not fully correct. They may pretend to
+ * be equal although they are not. But more correctness is not achievable based on the
+ * <code>toString</code> parameter. 
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 05.09.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public class JFCTraceCorrector  extends DefaultHandler {
+
+    /**
+     * <p>
+     * the file to write the result into
+     * </p>
+     */
+    private PrintStream outFile;
+    
+    /**
+     * <p>
+     * the currently parsed event
+     * </p>
+     */
+    private Event currentEvent;
+
+    /**
+     * <p>
+     * the currently parsed source of the currently parsed event
+     * </p>
+     */
+    private Source currentSource;
+
+    /**
+     * <p>
+     * the source of the last parsed event
+     * </p>
+     */
+    private Source lastSource;
+
+    /**
+     * <p>
+     * the currently parsed component of the currently parsed source of the currently parsed event
+     * </p>
+     */
+    private Component currentComponent;
+
+    /**
+     * <p>
+     * the currently parsed session
+     * </p>
+     */
+    private Session currentSession;
+
+    /**
+     * <p>
+     * corrects the given file and returns the name of the file into which the result was written
+     * </p>
+     * 
+     * @param filename the name of the file to be corrected
+     * 
+     * @return the name of the file with the corrected logfile
+     * 
+     * @throws IllegalArgumentException if the filename is null
+     */
+    public String correctFile(String filename) throws IllegalArgumentException {
+        if (filename == null) {
+            throw new IllegalArgumentException("filename must not be null");
+        }
+
+        return correctFile(new File(filename)).getAbsolutePath();
+    }
+
+    /**
+     * <p>
+     * corrects the given file, stores the result in the second provided file and returns the
+     * name of the file into which the result was written
+     * </p>
+     * 
+     * @param filename   the name of the file to be corrected
+     * @param resultFile the name of the file into which the corrected log shall be written
+     * 
+     * @return the name of the file with the corrected logfile
+     * 
+     * @throws IllegalArgumentException if the filename or resultFile is null
+     */
+    public String correctFile(String filename, String resultFile) throws IllegalArgumentException {
+        if ((filename == null) | (resultFile == null)) {
+            throw new IllegalArgumentException("filename and resultFile must not be null");
+        }
+
+        return correctFile(new File(filename), new File(resultFile)).getAbsolutePath();
+    }
+
+    /**
+     * <p>
+     * corrects the given file and returns the file into which the result was written. The name
+     * of the resulting file is contains the suffix "_corrected" before the dot.
+     * </p>
+     * 
+     * @param file the file to be corrected
+     * 
+     * @return the file containing the corrected logfile
+     * 
+     * @throws IllegalArgumentException if the file is null
+     */
+    public File correctFile(File file) throws IllegalArgumentException {
+        if (file == null) {
+            throw new IllegalArgumentException("file must not be null");
+        }
+
+        int index = file.getName().lastIndexOf('.');
+        String fileName =
+            file.getName().substring(0, index) + "_corrected" + file.getName().substring(index);
+
+        File resultFile = new File(file.getParentFile(), fileName);
+
+        return correctFile(file, resultFile);
+    }
+
+    /**
+     * <p>
+     * corrects the given file, stores the result in the second provided file and returns the
+     * file into which the result was written
+     * </p>
+     * 
+     * @param file       the file to be corrected
+     * @param resultFile the file into which the corrected log shall be written
+     * 
+     * @return the file with the corrected logfile
+     * 
+     * @throws IllegalArgumentException if the file or resultFile is null or if they are equal
+     */
+    public File correctFile(File file, File resultFile) throws IllegalArgumentException {
+        if ((file == null) || (resultFile == null)) {
+            throw new IllegalArgumentException("file and result file must not be null");
+        }
+        
+        if (file.getAbsolutePath().equals(resultFile.getAbsolutePath())) {
+            throw new IllegalArgumentException("file and result file must not be equal");
+        }
+        
+        try {
+            outFile = new PrintStream(new FileOutputStream(resultFile));
+            outFile.println("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
+        }
+        catch (FileNotFoundException e1) {
+            throw new IllegalArgumentException("could not create a corrected file name " +
+                                               resultFile + " next to " + file);
+        }
+        
+
+        SAXParserFactory spf = SAXParserFactory.newInstance();
+        spf.setValidating(true);
+
+        SAXParser saxParser = null;
+        InputSource inputSource = null;
+        try {
+            saxParser = spf.newSAXParser();
+            inputSource =
+                new InputSource(new InputStreamReader(new FileInputStream(file), "UTF-8"));
+        }
+        catch (UnsupportedEncodingException e) {
+            Console.printerr("Error parsing file + " + file.getName());
+            Console.logException(e);
+            return null;
+        }
+        catch (ParserConfigurationException e) {
+            Console.printerr("Error parsing file + " + file.getName());
+            Console.logException(e);
+            return null;
+        }
+        catch (SAXException e) {
+            Console.printerr("Error parsing file + " + file.getName());
+            Console.logException(e);
+            return null;
+        }
+        catch (FileNotFoundException e) {
+            Console.printerr("Error parsing file + " + file.getName());
+            Console.logException(e);
+            return null;
+        }
+        if (inputSource != null) {
+            inputSource.setSystemId("file://" + file.getAbsolutePath());
+            try {
+                if (saxParser == null) {
+                    throw new RuntimeException("SAXParser creation failed");
+                }
+                saxParser.parse(inputSource, this);
+            }
+            catch (SAXParseException e) {
+                Console.printerrln("Failure parsing file in line " + e.getLineNumber() +
+                    ", column " + e.getColumnNumber() + ".");
+                Console.logException(e);
+                return null;
+            }
+            catch (SAXException e) {
+                Console.printerr("Error parsing file + " + file.getName());
+                Console.logException(e);
+                return null;
+            }
+            catch (IOException e) {
+                Console.printerr("Error parsing file + " + file.getName());
+                Console.logException(e);
+                return null;
+            }
+        }
+        
+        if (outFile != null) {
+            outFile.close();
+        }
+        
+        return resultFile;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String,
+     * java.lang.String, org.xml.sax.Attributes)
+     */
+    public void startElement(String uri, String localName, String qName, Attributes atts)
+        throws SAXException
+    {
+        if (qName.equals("sessions")) {
+            currentSession = new Session();
+            currentSession.type = "sessions";
+        }
+        else if (qName.equals("newsession")) {
+            if (currentSession != null) {
+                currentSession.dump(outFile);
+            }
+            
+            currentSession = new Session();
+            currentSession.type = "newsession";
+        }
+        else if (qName.equals("event")) {
+            currentEvent = new Event();
+            currentEvent.id = atts.getValue("id");
+        }
+        else if (qName.equals("source")) {
+            currentSource = new Source();
+        }
+        else if (qName.equals("component")) {
+            currentComponent = new Component();
+        }
+        else if (qName.equals("param")) {
+            if (currentComponent != null) {
+                currentComponent.params.add
+                    (new String[] {atts.getValue("name"), atts.getValue("value") });
+            }
+            else if (currentSource != null) {
+                currentSource.params.add
+                    (new String[] {atts.getValue("name"), atts.getValue("value") });
+            }
+            else if (currentEvent != null) {
+                currentEvent.params.add
+                    (new String[] {atts.getValue("name"), atts.getValue("value") });
+            }
+            else {
+                throw new SAXException("parameter occurred at an unexpected place");
+            }
+        }
+        else {
+            throw new SAXException("unexpected tag " + qName);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String,
+     * java.lang.String)
+     */
+    @Override
+    public void endElement(String uri, String localName, String qName) throws SAXException {
+        if (qName.equals("sessions")) {
+            //harmonizeToStringComponents();
+
+            currentSession.dump(outFile);
+            currentSession = null;
+        }
+        else if (qName.equals("newsession")) {
+            //harmonizeToStringComponents();
+            
+            currentSession.dump(outFile);
+            currentSession = null;
+        }
+        else if (qName.equals("event")) {
+            currentSession.events.add(currentEvent);
+            currentEvent = null;
+        }
+        else if (qName.equals("source")) {
+            if (currentSource.components.size() == 0) {
+                correctEventSource(currentSource);
+            }
+            
+            lastSource = currentSource;
+            currentEvent.source = currentSource;
+            currentSource = null;
+        }
+        else if (qName.equals("component")) {
+            currentSource.components.add(currentComponent);
+            currentComponent = null;
+        }
+        else if (!qName.equals("param")) {
+            throw new SAXException("unexpected closing tag " + qName);
+        }
+
+    }
+
+    /**
+     * 
+     */
+    /*private void harmonizeToStringComponents() {
+        List<SourceGroup> groups = determineSourceGroups();
+        
+        for (SourceGroup group : groups) {
+            group.dump(System.out);
+        }
+    }*/
+
+    /**
+     *
+     */
+    /*private List<SourceGroup> determineSourceGroups() {
+        List<SourceGroup> groups = new ArrayList<SourceGroup>();
+        
+        for (Event event : currentSession.events) {
+            Source source = event.source;
+            Component lastComponent = source.components.get(source.components.size() - 1);
+            if (lastComponent instanceof ComponentFromToString) {
+                SourceGroup group = getSourceGroup(groups, source);
+                List<ComponentFromToString> sourcesWithSameXCoordinate =
+                    group.leafComponents.get(((ComponentFromToString) lastComponent).x);
+                
+                if (sourcesWithSameXCoordinate == null) {
+                    sourcesWithSameXCoordinate = new ArrayList<ComponentFromToString>();
+                    group.leafComponents.put
+                        (((ComponentFromToString) lastComponent).x, sourcesWithSameXCoordinate);
+                }
+                
+                if (!sourcesWithSameXCoordinate.contains(lastComponent)) {
+                    sourcesWithSameXCoordinate.add(((ComponentFromToString) lastComponent));
+                }
+            }
+        }
+        
+        return groups;
+    }*/
+
+    /**
+     * 
+     */
+    /*private SourceGroup getSourceGroup(List<SourceGroup> groups, Source source) {
+        SourceGroup resultingGroup = null;
+        
+        for (SourceGroup candidate : groups) {
+            if (candidate.parentComponents.size() == (source.components.size() - 1)) {
+                boolean allComponentsMatch = true;
+            
+                for (int i = 0; i < candidate.parentComponents.size(); i++) {
+                    if (!candidate.parentComponents.get(i).equals(source.components.get(i))) {
+                        allComponentsMatch = false;
+                        break;
+                    }
+                }
+                
+                if (allComponentsMatch) {
+                    resultingGroup = candidate;
+                    break;
+                }
+            }
+        }
+        
+        if (resultingGroup == null) {
+            resultingGroup = new SourceGroup();
+            
+            for (int i = 0; i < (source.components.size() - 1); i++) {
+                resultingGroup.parentComponents.add(source.components.get(i));
+            }
+            
+            groups.add(resultingGroup);
+        }
+        
+        return resultingGroup;
+    }*/
+
+    /**
+     * <p>
+     * corrects the source of an event. It copies all parameters of the source of the previous
+     * event if they are not included in the source already. Furthermore, it adds all components
+     * of the source of the previous event. At last, it adds a further component based on the
+     * information found in the <code>toString</code> parameter of the source.
+     * </p>
+     *
+     * @param source the source to be corrected
+     */
+    private void correctEventSource(Source source) {
+        for (String[] parameterOfLastSource : lastSource.params) {
+            boolean foundParameter = false;
+            for (String[] parameter : source.params) {
+                if (parameter[0].equals(parameterOfLastSource[0])) {
+                    foundParameter = true;
+                    break;
+                }
+            }
+            
+            if (!foundParameter) {
+                source.params.add(parameterOfLastSource);
+            }
+        }
+        
+        for (Component component : lastSource.components) {
+            if (!(component instanceof ComponentFromToString)) {
+                source.components.add(component);
+            }
+        }
+        
+        source.components.add(getComponentFromToString(source));
+    }
+
+    /**
+     * <p>
+     * determines a component based on the <code>toString</code> parameter of the provided source.
+     * For this, it parses the parameter value and tries to determine several infos such as the
+     * type and the name of it. The resulting components are not always distinguishable. This is,
+     * because the <code>toString</code> parameter does not contain sufficient information for
+     * correct identification.
+     * </p>
+     * 
+     * @param source the source to extract the <code>toString</code> parameter from
+     * 
+     * @return the component parsed from the <code>toString</code> parameter
+     */
+    private Component getComponentFromToString(Source source) {
+        String toStringValue = null;
+        
+        for (String[] parameter : source.params) {
+            if ("toString".equals(parameter[0])) {
+                toStringValue = parameter[1];
+                break;
+            }
+        }
+        
+        ComponentFromToString component = new ComponentFromToString();
+        
+        // search for the beginning of the parameters section. Up to this position we find the class
+        int start = toStringValue.indexOf('[');
+        String clazz = toStringValue.substring(0, start);
+        
+        // the first parameters are x and y coordinate as well as the size. The size is one
+        // parameter, where with and height are separated with an 'x'
+        start = toStringValue.indexOf(',', start) + 1;
+        int end = toStringValue.indexOf(',', start);
+        
+        component.x = Integer.parseInt(toStringValue.substring(start, end));
+        
+        start = end + 1;
+        end = toStringValue.indexOf(',', start);
+
+        component.y = Integer.parseInt(toStringValue.substring(start, end));
+
+        start = end + 1;
+        end = toStringValue.indexOf('x', start);
+
+        component.width = Integer.parseInt(toStringValue.substring(start, end));
+
+        start = end + 1;
+        end = toStringValue.indexOf(',', start);
+
+        component.height = Integer.parseInt(toStringValue.substring(start, end));
+
+        // no start parsing the rest of the parameters and extract those having a key and a 
+        // value and whose key is text, defaultIcon, or an alignment
+        int intermediate;
+        start = end + 1;
+
+        String title = null;
+        String icon = null;
+        String alignment = null;
+        
+        do {
+            end = toStringValue.indexOf(',', start);
+            intermediate = toStringValue.indexOf('[', start);
+            
+            if ((intermediate >= 0) && (intermediate < end)) {
+                // the value of the parameter itself contains brackets. So try to determine the 
+                // real end of the parameter
+                end = toStringValue.indexOf(']', intermediate);
+                end = toStringValue.indexOf(',', end);
+            }
+            
+            if (end < 0) {
+                //we reached the end of the stream. So the the end to the "end"
+                end = toStringValue.lastIndexOf(']');
+            }
+            
+            intermediate = toStringValue.indexOf('=', start);
+            
+            if ((intermediate >= 0) && (intermediate < end)) {
+                // this is a key value pair, so store the the parameter
+                String key = toStringValue.substring(start, intermediate);
+                String value = toStringValue.substring(intermediate + 1, end);
+                
+                if ("text".equals(key)) {
+                    title = value;
+                }
+                else if ("defaultIcon".equals(key)) {
+                    icon = value;
+                }
+                else if ("alignmentX".equals(key) || "alignmentY".equals(key)) {
+                    if (alignment == null) {
+                        alignment = value;
+                    }
+                    else {
+                        alignment += "/" + value;
+                    }
+                }
+            }
+            /*else {
+                // this is a simple value, for now simply ignore it
+                String key = toStringValue.substring(start, end);
+                if (!"invalid".equals(key)) {
+                    componentHash += key.hashCode();
+                    component.params.add(new String[] { key, "true" });
+                }
+            }*/
+            
+            start = end + 1;
+        }
+        while (start < toStringValue.lastIndexOf(']'));
+        
+        // finish the component specification by setting the parameters
+        if (title == null) {
+            if (icon == null) {
+                title = clazz.substring(clazz.lastIndexOf('.') + 1) + "(";
+                
+                // to be able to distinguish some elements, that usually have no name and icon, try
+                // to include some of their specific identifying information in their name.
+                if ("org.tigris.gef.presentation.FigTextEditor".equals(clazz) ||
+                    "org.argouml.core.propertypanels.ui.UMLTextField".equals(clazz))
+                {
+                    title += "height " + component.height + ", ";
+                }
+                else if ("org.argouml.core.propertypanels.ui.UMLLinkedList".equals(clazz) ||
+                         "org.argouml.core.propertypanels.ui.LabelledComponent".equals(clazz))
+                {
+                    title += "position " + component.x + "/" + component.y + ", ";
+                }
+                
+                title += "alignment " + alignment + ")";
+            }
+            else {
+                title = icon;
+            }
+        }
+        
+        component.params.add(new String[] { "title", title } );
+        component.params.add(new String[] { "class", clazz } );
+        component.params.add(new String[] { "icon", icon } );
+        component.params.add(new String[] { "index", "-1" });
+        
+        int hashCode = clazz.hashCode() + title.hashCode();
+        
+        if (hashCode < 0) {
+            hashCode = -hashCode;
+        }
+        
+        component.params.add(new String[] { "hash", Integer.toString(hashCode, 16) });
+
+        return component;
+    }    
+
+    /**
+     * <p>
+     * used to dump a list of parameters to the provided print stream
+     * </p>
+     */
+    private void dumpParams(PrintStream out, List<String[]> params, String indent) {
+        for (String[] param : params) {
+            out.print(indent);
+            out.print("<param name=\"");
+            out.print(param[0]);
+            out.print("\" value=\"");
+            out.print(param[1]);
+            out.println("\" />");
+        }
+        
+    }
+    
+    /**
+     * <p>
+     * used to carry all events of a session and to dump it to the output file
+     * </p> 
+     */
+    private class Session {
+        private String type;
+        private List<Event> events = new ArrayList<Event>();
+        
+        public void dump(PrintStream out) {
+            out.print("<");
+            out.print(type);
+            out.println(">");
+
+            for (Event event : events) {
+                event.dump(out);
+            }
+            
+            out.print("</");
+            out.print(type);
+            out.println(">");
+        }
+    }
+
+    /**
+     * <p>
+     * used to carry all information about an event and to dump it to the output file
+     * </p> 
+     */
+    private class Event {
+        private String id;
+        private List<String[]> params = new ArrayList<String[]>();
+        private Source source;
+        
+        private void dump(PrintStream out) {
+            out.print("<event id=\"");
+            out.print(id);
+            out.println("\">");
+            
+            dumpParams(out, params, " ");
+            source.dump(out);
+            
+            out.println("</event>");
+        }
+    }
+
+    /**
+     * <p>
+     * used to carry all information about a source of an event and to dump it to the output file
+     * </p> 
+     */
+    private class Source {
+        private List<String[]> params = new ArrayList<String[]>();
+        private List<Component> components = new ArrayList<Component>();
+
+        private void dump(PrintStream out) {
+            out.println(" <source>");
+            
+            dumpParams(out, params, "  ");
+            
+            for (Component component : components) {
+                component.dump(out);
+            }
+            
+            out.println(" </source>");
+        }
+    }
+    
+    /**
+     * <p>
+     * used to carry all information about a component of a source and to dump it to the output file
+     * </p> 
+     */
+    private class Component {
+        protected List<String[]> params = new ArrayList<String[]>();
+        
+        protected void dump(PrintStream out) {
+            out.println("  <component>");
+            dumpParams(out, params, "   ");
+            out.println("  </component>");
+        }
+
+        public boolean equals(Object other) {
+            if (this == other) {
+                return true;
+            }
+            
+            if (!(other instanceof Component)) {
+                return false;
+            }
+            
+            Component otherComp = (Component) other;
+            
+            boolean allParamsEqual = (params.size() == otherComp.params.size());
+            
+            if (allParamsEqual) {
+                for (int i = 0; i < params.size(); i++) {
+                    if (!params.get(i)[0].equals(otherComp.params.get(i)[0]) &&
+                        !params.get(i)[1].equals(otherComp.params.get(i)[1]))
+                    {
+                        allParamsEqual = false;
+                        break;
+                    }
+                }
+            }
+            
+            return allParamsEqual;
+        }
+    }
+
+    /**
+     * <p>
+     * represents a specific component, which was read from the toString parameter of a source
+     * </p> 
+     */
+    private class ComponentFromToString extends Component {
+        private int x;
+        private int y;
+        private int width;
+        private int height;
+        
+        @Override
+        protected void dump(PrintStream out) {
+            out.println("  <component>");
+            
+            out.print("   ");
+            out.print("<param name=\"x\" value=\"");
+            out.print(x);
+            out.println("\" />");
+
+            out.print("   ");
+            out.print("<param name=\"y\" value=\"");
+            out.print(y);
+            out.println("\" />");
+
+            out.print("   ");
+            out.print("<param name=\"width\" value=\"");
+            out.print(width);
+            out.println("\" />");
+
+            out.print("   ");
+            out.print("<param name=\"height\" value=\"");
+            out.print(height);
+            out.println("\" />");
+
+            dumpParams(out, params, "   ");
+            out.println("  </component>");
+        }
+        
+        /*public boolean equals(Object other) {
+            if (this == other) {
+                return true;
+            }
+            
+            if (!(other instanceof ComponentFromToString)) {
+                return false;
+            }
+            
+            ComponentFromToString otherComp = (ComponentFromToString) other;
+            
+            // ignore the coordinates and the width as it may change over time
+            boolean allParamsEqual =
+                (height == otherComp.height) && (params.size() == otherComp.params.size());
+            
+            if (allParamsEqual) {
+                for (int i = 0; i < params.size(); i++) {
+                    if (!"x".equals(params.get(i)[0]) && !"y".equals(params.get(i)[0]) &&
+                        !"width".equals(params.get(i)[0]) && !"height".equals(params.get(i)[0]) &&
+                        !"index".equals(params.get(i)[0]) && !"hash".equals(params.get(i)[0]) &&
+                        !params.get(i)[0].equals(otherComp.params.get(i)[0]) &&
+                        !params.get(i)[1].equals(otherComp.params.get(i)[1]))
+                    {
+                        allParamsEqual = false;
+                        break;
+                    }
+                }
+            }
+            
+            return allParamsEqual;
+        }*/
+    }
+
+    /**
+     * 
+     */
+    /*private class SourceGroup {
+        protected List<Component> parentComponents = new ArrayList<Component>();
+        protected Map<Integer, List<ComponentFromToString>> leafComponents =
+            new HashMap<Integer, List<ComponentFromToString>>();
+
+        private void dump(PrintStream out) {
+            out.println("source group:");
+            
+            for (Map.Entry<Integer, List<ComponentFromToString>> entry : leafComponents.entrySet())
+            {
+                out.print("    x-coordinate = ");
+                out.println(entry.getKey());
+                for (ComponentFromToString leafComponent : entry.getValue()) {
+                    leafComponent.dump(out);
+                }
+                
+                out.println();
+            }
+        }
+    }*/
+
+}
Index: /trunk/quest-plugin-jfc/src/main/java/de/ugoe/cs/quest/plugin/jfc/commands/CMDcorrectDirOldJFC.java
===================================================================
--- /trunk/quest-plugin-jfc/src/main/java/de/ugoe/cs/quest/plugin/jfc/commands/CMDcorrectDirOldJFC.java	(revision 787)
+++ /trunk/quest-plugin-jfc/src/main/java/de/ugoe/cs/quest/plugin/jfc/commands/CMDcorrectDirOldJFC.java	(revision 787)
@@ -0,0 +1,77 @@
+
+package de.ugoe.cs.quest.plugin.jfc.commands;
+
+import java.io.File;
+import java.util.List;
+import java.util.logging.Level;
+
+import de.ugoe.cs.quest.plugin.jfc.JFCTraceCorrector;
+import de.ugoe.cs.util.console.Command;
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * <p>
+ * Command that tries to correct all files in a folder as if they were log files generated by the
+ * older version of the JFCMonitor which sometimes do not include correct event sources. The result
+ * is another specified directory, which contains the corrected files.
+ * </p>
+ * 
+ * @author Patrick Harms
+ * @version 1.0
+ */
+public class CMDcorrectDirOldJFC implements Command {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.util.console.Command#run(java.util.List)
+     */
+    @Override
+    public void run(List<Object> parameters) {
+        String path;
+        String resultPath;
+
+        try {
+            path = (String) parameters.get(0);
+            resultPath = (String) parameters.get(1);
+        }
+        catch (Exception e) {
+            throw new IllegalArgumentException();
+        }
+
+        File folder = new File(path);
+        if (!folder.isDirectory()) {
+            Console.printerrln(path + " is not a directory");
+            return;
+        }
+
+        File destfolder = new File(resultPath);
+        if (!destfolder.isDirectory()) {
+            Console.printerrln(resultPath + " is not a directory");
+            return;
+        }
+
+        JFCTraceCorrector corrector = new JFCTraceCorrector();
+
+        String absolutPath = folder.getAbsolutePath();
+        String absolutDestPath = destfolder.getAbsolutePath();
+        for (String filename : folder.list()) {
+            String source = absolutPath + "/" + filename;
+            String dest = absolutDestPath + "/" + filename;
+            Console.traceln(Level.INFO, "Processing file: " + source);
+
+            corrector.correctFile(source, dest);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.util.console.Command#help()
+     */
+    @Override
+    public String help() {
+        return "correctDirOldJFC <sourcedirectory> <destinationdirectory>";
+    }
+
+}
Index: /trunk/quest-plugin-jfc/src/main/java/de/ugoe/cs/quest/plugin/jfc/commands/CMDcorrectOldJFC.java
===================================================================
--- /trunk/quest-plugin-jfc/src/main/java/de/ugoe/cs/quest/plugin/jfc/commands/CMDcorrectOldJFC.java	(revision 787)
+++ /trunk/quest-plugin-jfc/src/main/java/de/ugoe/cs/quest/plugin/jfc/commands/CMDcorrectOldJFC.java	(revision 787)
@@ -0,0 +1,53 @@
+
+package de.ugoe.cs.quest.plugin.jfc.commands;
+
+import java.util.List;
+
+import de.ugoe.cs.quest.plugin.jfc.JFCTraceCorrector;
+import de.ugoe.cs.util.console.Command;
+
+/**
+ * <p>
+ * Command to correct an XML file with sessions monitored by the older version of the
+ * EventBench's JFCMonitor which sometimes do not include correct event sources.
+ * </p>
+ * 
+ * @author Patrick Harms
+ * @version 1.0
+ */
+public class CMDcorrectOldJFC implements Command {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.util.console.Command#run(java.util.List)
+     */
+    @Override
+    public void run(List<Object> parameters) {
+        String inputfilename;
+        String outputfilename;
+
+        try {
+            inputfilename = (String) parameters.get(0);
+            outputfilename = (String) parameters.get(1);
+        }
+        catch (Exception e) {
+            throw new IllegalArgumentException();
+        }
+
+        JFCTraceCorrector corrector = new JFCTraceCorrector();
+
+        corrector.correctFile(inputfilename, outputfilename);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.util.console.Command#help()
+     */
+    @Override
+    public String help() {
+        return "correctOldJFC <inputfilename> <outputfilename>";
+    }
+
+}
Index: /trunk/quest-plugin-jfc/src/main/resources/manuals/correctDirOldJFC
===================================================================
--- /trunk/quest-plugin-jfc/src/main/resources/manuals/correctDirOldJFC	(revision 787)
+++ /trunk/quest-plugin-jfc/src/main/resources/manuals/correctDirOldJFC	(revision 787)
@@ -0,0 +1,9 @@
+corrects older JFC log files contained in a directory which sometimes do not contain correct event
+sources. The result is another directory containing the corrected log files.
+
+$USAGE$
+<sourcedirectory> name of the source directory containing the older JFC log file
+<destinationdirectory> name of the destination directory into which the corrected log files shall be stored. Must not be equal to the sourcedirectory
+
+Example(s):
+correctDirOldJFC usagedata/jfc_old usagedata/jfc_new
Index: /trunk/quest-plugin-jfc/src/main/resources/manuals/correctOldJFC
===================================================================
--- /trunk/quest-plugin-jfc/src/main/resources/manuals/correctOldJFC	(revision 787)
+++ /trunk/quest-plugin-jfc/src/main/resources/manuals/correctOldJFC	(revision 787)
@@ -0,0 +1,8 @@
+corrects an older JFC log file which sometimes does not contain correct event sources
+
+$USAGE$
+<inputfilename> name of the older JFC log file
+<outputfilename> name of the new JFC log file to write the results into. Must not be equal to the inputfilename
+
+Example(s):
+correctOldJFC usagedata/jfc/jfclog_01.xml usagedata/jfc/jfclog_01_corrected.xml
