Index: /trunk/autoquest-core-usability/.classpath
===================================================================
--- /trunk/autoquest-core-usability/.classpath	(revision 896)
+++ /trunk/autoquest-core-usability/.classpath	(revision 896)
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry including="**/*.java" kind="src" path="src/main/resources"/>
+	<classpathentry including="**/*.java" kind="src" output="target/classes" path="target/generated-sources/xjc">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
Index: /trunk/autoquest-core-usability/.project
===================================================================
--- /trunk/autoquest-core-usability/.project	(revision 896)
+++ /trunk/autoquest-core-usability/.project	(revision 896)
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>quest-core-usability</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
Index: /trunk/autoquest-core-usability/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- /trunk/autoquest-core-usability/.settings/org.eclipse.jdt.core.prefs	(revision 896)
+++ /trunk/autoquest-core-usability/.settings/org.eclipse.jdt.core.prefs	(revision 896)
@@ -0,0 +1,12 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
Index: /trunk/autoquest-core-usability/.settings/org.eclipse.m2e.core.prefs
===================================================================
--- /trunk/autoquest-core-usability/.settings/org.eclipse.m2e.core.prefs	(revision 896)
+++ /trunk/autoquest-core-usability/.settings/org.eclipse.m2e.core.prefs	(revision 896)
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
Index: /trunk/autoquest-core-usability/pom.xml
===================================================================
--- /trunk/autoquest-core-usability/pom.xml	(revision 896)
+++ /trunk/autoquest-core-usability/pom.xml	(revision 896)
@@ -0,0 +1,39 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <groupId>de.ugoe.cs.quest</groupId>
+    <artifactId>quest</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>quest-core-usability</artifactId>
+  <name>quest-core-usability</name>
+  <scm>
+    <url>${quest-scm-trunk-dir}/quest-core-usability</url>
+  </scm>
+  <dependencies>
+    <dependency>
+        <groupId>de.ugoe.cs.quest</groupId>
+        <artifactId>quest-core-tasktrees</artifactId>
+        <version>${project.parent.version}</version>
+    </dependency>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.jvnet.jaxb2.maven2</groupId>
+        <artifactId>maven-jaxb2-plugin</artifactId>
+        <version>0.8.2</version>
+        <configuration>
+          <generatePackage>de.ugoe.cs.quest.usability</generatePackage>
+        </configuration>
+        <executions>
+          <execution>
+            <goals>
+              <goal>generate</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
Index: /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/TextInputStatisticsRule.java
===================================================================
--- /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/TextInputStatisticsRule.java	(revision 896)
+++ /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/TextInputStatisticsRule.java	(revision 896)
@@ -0,0 +1,400 @@
+package de.ugoe.cs.quest.usability;
+
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import de.ugoe.cs.quest.eventcore.gui.TextInput;
+import de.ugoe.cs.quest.eventcore.guimodel.ITextArea;
+import de.ugoe.cs.quest.eventcore.guimodel.ITextField;
+import de.ugoe.cs.quest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTree;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 16.07.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public class TextInputStatisticsRule implements de.ugoe.cs.quest.usability.UsabilityEvaluationRule {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.usability.UsabilityEvaluationRule#evaluate(TaskTree)
+     */
+    @Override
+    public UsabilityEvaluationResult evaluate(ITaskTree taskTree) {
+        TextInputStatistics statistics = new TextInputStatistics();
+        calculateStatistics(taskTree.getRoot(), statistics);
+
+        UsabilityEvaluationResult results = new UsabilityEvaluationResult();
+        analyzeStatistics(statistics, results);
+
+        return results;
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param statistics
+     * @param results
+     */
+    private void analyzeStatistics(TextInputStatistics       statistics,
+                                   UsabilityEvaluationResult results)
+    {
+        checkTextInputRatio(statistics, results);
+        checkTextFieldEntryRepetitions(statistics, results);
+        checkTextFieldNoLetterOrDigitInputs(statistics, results);
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param statistics
+     * @param results
+     */
+    private void checkTextInputRatio(TextInputStatistics       statistics,
+                                     UsabilityEvaluationResult results)
+    {
+        float allTextFieldInputs =
+            statistics.getNoOfTextFieldInputs() + statistics.getNoOfTextAreaInputs();
+
+        float ratio = allTextFieldInputs / (float) statistics.getNoOfAllEvents();
+
+        UsabilityDefectSeverity severity = null;
+        if (ratio > 0.9) {
+            severity = UsabilityDefectSeverity.HIGH;
+        }
+        else if (ratio > 0.7) {
+            severity = UsabilityDefectSeverity.MEDIUM;
+        }
+        else if (ratio > 0.5) {
+            severity = UsabilityDefectSeverity.LOW;
+        }
+        else if (ratio > 0.3) {
+            severity = UsabilityDefectSeverity.INFO;
+        }
+
+        if (severity != null) {
+            Map<String, String> parameters = new HashMap<String, String>();
+            parameters.put("textInputRatio", DecimalFormat.getInstance().format(ratio * 100) + "%");
+
+            results.addDefect
+                (new UsabilityDefect(severity, UsabilityDefectDescription.TEXT_FIELD_INPUT_RATIO,
+                                     parameters));
+        }
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param statistics
+     * @param results
+     */
+    private void checkTextFieldEntryRepetitions(TextInputStatistics       statistics,
+                                                UsabilityEvaluationResult results)
+    {
+        Map<String, Integer> words = new HashMap<String, Integer>();
+        int numberOfRepeatedWords = 0;
+        int maxRepetitions = 0;
+
+        for (int i = 0; i < statistics.getNoOfTextFieldInputs(); i++) {
+            String[] fragments = statistics.getTextFieldInputFragments(i);
+            for (String fragment : fragments) {
+                if (!"".equals(fragment.trim())) {
+                    Integer count = words.get(fragment);
+                    if (count == null) {
+                        words.put(fragment, 1);
+                    }
+                    else {
+                        count++;
+                        words.put(fragment, count);
+                        maxRepetitions = Math.max(count, maxRepetitions);
+
+                        if (count == 2) {
+                            // do not calculate repeated words several times
+                            numberOfRepeatedWords++;
+                        }
+                    }
+                }
+            }
+        }
+
+        UsabilityDefectSeverity severity = null;
+        if ((numberOfRepeatedWords > 10) || (maxRepetitions > 10)) {
+            severity = UsabilityDefectSeverity.HIGH;
+        }
+        else if ((numberOfRepeatedWords > 4) || (maxRepetitions > 4)) {
+            severity = UsabilityDefectSeverity.MEDIUM;
+        }
+        else if ((numberOfRepeatedWords > 2) || (maxRepetitions > 2)) {
+            severity = UsabilityDefectSeverity.LOW;
+        }
+        else if ((numberOfRepeatedWords > 1) || (maxRepetitions > 1)) {
+            severity = UsabilityDefectSeverity.INFO;
+        }
+
+        if (severity != null) {
+            Map<String, String> parameters = new HashMap<String, String>();
+            parameters.put("textRepetitionRatio", numberOfRepeatedWords +
+                           " repeated tokens, up to " + maxRepetitions + " repetitions per token");
+
+            results.addDefect
+                (new UsabilityDefect(severity,
+                                     UsabilityDefectDescription.TEXT_FIELD_INPUT_REPETITIONS,
+                                     parameters));
+        }
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param statistics
+     * @param results
+     */
+    private void checkTextFieldNoLetterOrDigitInputs(TextInputStatistics       statistics,
+                                                     UsabilityEvaluationResult results)
+    {
+        int allCharactersCount = 0;
+        int noLetterOrDigitCount = 0;
+
+        for (int i = 0; i < statistics.getNoOfTextFieldInputs(); i++) {
+            String[] fragments = statistics.getTextFieldInputFragments(i);
+            for (String fragment : fragments) {
+                String effectiveFragment = fragment.trim();
+                for (int j = 0; j < effectiveFragment.length(); j++) {
+                    if (!Character.isWhitespace(effectiveFragment.charAt(j))) {
+                        if (!Character.isLetterOrDigit(effectiveFragment.charAt(j))) {
+                            noLetterOrDigitCount++;
+                        }
+                        allCharactersCount++;
+                    }
+                }
+            }
+        }
+
+        float ratio = (float) noLetterOrDigitCount / (float) allCharactersCount;
+
+        UsabilityDefectSeverity severity = null;
+        if (ratio > 0.1) // every 10th sign
+        {
+            severity = UsabilityDefectSeverity.HIGH;
+        }
+        else if (ratio > 0.05) // every 20th sign
+        {
+            severity = UsabilityDefectSeverity.MEDIUM;
+        }
+        else if (ratio > 0.02) // every 50th sign
+        {
+            severity = UsabilityDefectSeverity.LOW;
+        }
+        else if (ratio > 0.01) // every 100th sign
+        {
+            severity = UsabilityDefectSeverity.INFO;
+        }
+
+        if (severity != null) {
+            Map<String, String> parameters = new HashMap<String, String>();
+            parameters.put("noLetterOrDigitRatio", allCharactersCount + " entered characters of " +
+                           "which " + noLetterOrDigitCount + " were no letter or digit");
+
+            results.addDefect
+                (new UsabilityDefect(severity,
+                                     UsabilityDefectDescription.TEXT_FIELD_NO_LETTER_OR_DIGIT_RATIO,
+                                     parameters));
+        }
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param taskTree
+     * @param statistics
+     */
+    private void calculateStatistics(ITaskTreeNode node, TextInputStatistics statistics) {
+        if ((node instanceof IEventTask) &&
+            (((IEventTask) node).getEventType() instanceof TextInput))
+        {
+            calculateStatistics((IEventTask) node, statistics);
+        }
+        else {
+            if ((node.getChildren() == null) || (node.getChildren().size() == 0)) {
+                statistics.incrementNoOfOtherEventTasks();
+            }
+            else {
+                for (ITaskTreeNode child : node.getChildren()) {
+                    calculateStatistics(child, statistics);
+                }
+            }
+        }
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param taskTree
+     * @param statistics
+     */
+    private void calculateStatistics(IEventTask node, TextInputStatistics statistics) {
+        String[] fragments =
+            determineTextFragments(((TextInput) node.getEventType()).getEnteredText());
+
+        if (node.getEventTarget() instanceof ITextField) {
+            statistics.addTextFieldInput(node, fragments);
+        }
+        else if (node.getEventTarget() instanceof ITextArea) {
+            statistics.addTextAreaInput(node, fragments);
+        }
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param enteredText
+     * @return
+     */
+    private String[] determineTextFragments(String enteredText) {
+        List<String> fragments = new ArrayList<String>();
+
+        StringBuffer fragment = new StringBuffer();
+        char lastChar = 0;
+
+        for (int i = 0; i < enteredText.length(); i++) {
+            char currentChar = enteredText.charAt(i);
+
+            if (!isEqualCharacterType(lastChar, currentChar)) {
+                // the previous fragment ended. so finalize it and start a new one
+                if ((fragment != null) && (fragment.length() > 0)) {
+                    fragments.add(fragment.toString());
+                    fragment = new StringBuffer();
+                }
+            }
+
+            fragment.append(currentChar);
+            lastChar = currentChar;
+        }
+
+        if ((fragment != null) && (fragment.length() > 0)) {
+            fragments.add(fragment.toString());
+        }
+
+        return fragments.toArray(new String[fragments.size()]);
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param lastChar
+     * @param currentChar
+     * @return
+     */
+    private boolean isEqualCharacterType(char char1, char char2) {
+        return
+            ((char1 == char2) ||
+            (Character.isWhitespace(char1) && Character.isWhitespace(char2)) ||
+            (Character.isDigit(char1) && Character.isDigit(char2)) ||
+            (Character.isLetter(char1) && Character.isLetter(char2)) ||
+            (Character.isJavaIdentifierPart(char1) && Character.isJavaIdentifierPart(char2)));
+    }
+
+    /**
+     * TODO comment
+     * 
+     * @version $Revision: $ $Date: 16.07.2012$
+     * @author 2012, last modified by $Author: pharms$
+     */
+    public static class TextInputStatistics {
+        
+        /** */
+        private List<Object[]> textFieldInputs = new ArrayList<Object[]>();
+
+        /** */
+        private List<Object[]> textAreaInputs = new ArrayList<Object[]>();
+
+        /** */
+        private int otherEventsCount;
+
+        /**
+         * TODO: comment
+         * 
+         * @param node
+         * @param fragments
+         * 
+         */
+        public void addTextFieldInput(IEventTask node, String[] fragments) {
+            textFieldInputs.add(new Object[] { node, fragments });
+        }
+
+        /**
+         * TODO: comment
+         * 
+         * @param node
+         * @param fragments
+         * 
+         */
+        public void addTextAreaInput(IEventTask node, String[] fragments) {
+            textAreaInputs.add(new Object[] { node, fragments });
+        }
+
+        /**
+         * TODO: comment
+         * 
+         * @return
+         */
+        public int getNoOfAllEvents() {
+            return textFieldInputs.size() + textAreaInputs.size() + otherEventsCount;
+        }
+
+        /**
+         * TODO: comment
+         * 
+         * @return
+         */
+        public int getNoOfTextFieldInputs() {
+            return textFieldInputs.size();
+        }
+
+        /**
+         * TODO: comment
+         * 
+         * @param i
+         * @return
+         */
+        public String[] getTextFieldInputFragments(int index) {
+            return (String[]) textFieldInputs.get(index)[1];
+        }
+
+        /**
+         * TODO: comment
+         * 
+         * @return
+         */
+        public int getNoOfTextAreaInputs() {
+            return textAreaInputs.size();
+        }
+
+        /**
+         * TODO: comment
+         * 
+         * @param i
+         * @return
+         */
+        public String[] getTextAreaInputFragments(int index) {
+            return (String[]) textAreaInputs.get(index)[1];
+        }
+
+        /**
+         * TODO: comment
+         * 
+         */
+        public void incrementNoOfOtherEventTasks() {
+            otherEventsCount++;
+        }
+
+    }
+
+}
Index: /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/UsabilityDefect.java
===================================================================
--- /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/UsabilityDefect.java	(revision 896)
+++ /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/UsabilityDefect.java	(revision 896)
@@ -0,0 +1,117 @@
+package de.ugoe.cs.quest.usability;
+
+import java.util.Map;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 16.07.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public class UsabilityDefect {
+
+    /** */
+    private UsabilityDefectSeverity severity;
+
+    /** */
+    private UsabilityDefectDescription description;
+
+    /** */
+    private Map<String, String> descriptionParameters;
+
+    /**
+     * TODO: comment
+     * 
+     * @param medium
+     * @param highTextInputRatio
+     */
+    public UsabilityDefect(UsabilityDefectSeverity severity, UsabilityDefectDescription description)
+    {
+        this(severity, description, null);
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param medium
+     * @param highTextInputRatio
+     */
+    public UsabilityDefect(UsabilityDefectSeverity    severity,
+                           UsabilityDefectDescription description,
+                           Map<String, String>        parameters)
+    {
+        this.severity = severity;
+        this.description = description;
+        this.descriptionParameters = parameters;
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @return
+     */
+    public UsabilityDefectSeverity getSeverity() {
+        return severity;
+    }
+
+    /**
+     * @param severity
+     *            the severity to set
+     */
+    public void setSeverity(UsabilityDefectSeverity severity) {
+        this.severity = severity;
+    }
+
+    /**
+     * @param description
+     *            the description to set
+     */
+    public void setDescription(UsabilityDefectDescription description) {
+        this.description = description;
+    }
+
+    /**
+   * 
+   */
+    public String getParameterizedDescription() {
+        return description.toString(descriptionParameters);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof UsabilityDefect) {
+            return
+                (severity == ((UsabilityDefect) obj).severity) &&
+                (description == ((UsabilityDefect) obj).description);
+        }
+        else {
+            return false;
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return severity.hashCode() + description.hashCode();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "UsabilityDefect(" + severity.name() + ", " + description.name() + ")";
+    }
+
+}
Index: /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/UsabilityDefectDescription.java
===================================================================
--- /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/UsabilityDefectDescription.java	(revision 896)
+++ /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/UsabilityDefectDescription.java	(revision 896)
@@ -0,0 +1,191 @@
+package de.ugoe.cs.quest.usability;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.Unmarshaller;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 18.07.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public enum UsabilityDefectDescription {
+    
+    TEXT_FIELD_INPUT_RATIO,
+    TEXT_FIELD_INPUT_REPETITIONS,
+    TEXT_FIELD_NO_LETTER_OR_DIGIT_RATIO;
+
+    /** */
+    private static final String DEFAULT_MESSAGES_FILE = "defectDescriptions_en.xml";
+
+    /** */
+    private static DefectDescriptions sDefectDescriptions;
+
+    /** */
+    private DefectDescription defectDescription;
+
+    /**
+     * TODO: comment
+     * 
+     * @param name
+     * @param ordinal
+     */
+    private UsabilityDefectDescription() {
+        init();
+    }
+
+    /**
+     * TODO: comment
+     * 
+     */
+    @SuppressWarnings("unchecked")
+    private void init() {
+        synchronized (this.getClass()) {
+            if (sDefectDescriptions == null) {
+                InputStream inputStream =
+                    ClassLoader.getSystemResourceAsStream(DEFAULT_MESSAGES_FILE);
+
+                try {
+                    String packageName = DefectDescriptions.class.getPackage().getName();
+                    JAXBContext jaxbContext = JAXBContext.newInstance(packageName);
+                    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+
+                    sDefectDescriptions =
+                        ((JAXBElement<DefectDescriptions>) unmarshaller.unmarshal(inputStream))
+                            .getValue();
+                }
+                catch (Exception e) {
+                    throw new RuntimeException
+                        ("error while initializing usability defect descriptions", e);
+                }
+                finally {
+                    if (inputStream != null) {
+                        try {
+                            inputStream.close();
+                        }
+                        catch (IOException e) {
+                            // ignore
+                        }
+                    }
+                }
+            }
+        }
+
+        for (DefectDescription description : sDefectDescriptions.getDefectDescription()) {
+            if (this.name().equals(description.getDefectId())) {
+                defectDescription = description;
+                break;
+            }
+        }
+
+        if (defectDescription == null) {
+            throw new RuntimeException
+                ("error while initializing usability defect descriptions. No " +
+                 "description text available for description " + this.name());
+        }
+    }
+
+    /**
+   * 
+   */
+    public String[] getDescriptionParameters() {
+        List<String> parameters = new ArrayList<String>();
+
+        for (Object fragment : defectDescription.getTextFragmentOrParameterFragment()) {
+            if (fragment instanceof ParameterFragment) {
+                parameters.add(((ParameterFragment) fragment).getParameterName());
+            }
+        }
+
+        return parameters.toArray(new String[parameters.size()]);
+    }
+
+    /**
+   * 
+   */
+    public String toString(Map<String, String> parameters) throws IllegalArgumentException {
+        StringBuffer result = new StringBuffer();
+
+        for (Object fragment : defectDescription.getTextFragmentOrParameterFragment()) {
+            if (result.length() > 0) {
+                result.append(" ");
+            }
+
+            if (fragment instanceof ParameterFragment) {
+                String value = null;
+                if (parameters != null) {
+                    value = parameters.get(((ParameterFragment) fragment).getParameterName());
+                }
+
+                if (value != null) {
+                    result.append(value);
+                }
+                else {
+                    throw new IllegalArgumentException
+                        ("required parameter \"" +
+                         ((ParameterFragment) fragment).getParameterName() +
+                         "\" for usability defect description " + this.name() + " not provided");
+                }
+            }
+            else {
+                result.append(getFragmentString(fragment));
+            }
+        }
+
+        return result.toString();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Enum#toString()
+     */
+    @Override
+    public String toString() {
+        StringBuffer result = new StringBuffer();
+
+        int paramCount = 1;
+        for (Object fragment : defectDescription.getTextFragmentOrParameterFragment()) {
+            if (result.length() > 0) {
+                result.append(" ");
+            }
+
+            if (fragment instanceof ParameterFragment) {
+                result.append("<parameter");
+                result.append(paramCount++);
+                result.append(">");
+            }
+            else {
+                result.append(getFragmentString(fragment));
+            }
+        }
+
+        return result.toString();
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param fragment
+     * @return
+     */
+    private String getFragmentString(Object fragment) {
+        String fragmentStr = fragment.toString().trim();
+
+        fragmentStr = fragmentStr.replaceAll("\n", " ");
+
+        while (fragmentStr.indexOf("  ") > -1) {
+            fragmentStr = fragmentStr.replaceAll("  ", " ");
+        }
+
+        return fragmentStr;
+    }
+
+}
Index: /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/UsabilityDefectSeverity.java
===================================================================
--- /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/UsabilityDefectSeverity.java	(revision 896)
+++ /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/UsabilityDefectSeverity.java	(revision 896)
@@ -0,0 +1,13 @@
+package de.ugoe.cs.quest.usability;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 16.07.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public enum UsabilityDefectSeverity {
+    
+    INFO, LOW, MEDIUM, HIGH;
+
+}
Index: /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/UsabilityEvaluationManager.java
===================================================================
--- /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/UsabilityEvaluationManager.java	(revision 896)
+++ /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/UsabilityEvaluationManager.java	(revision 896)
@@ -0,0 +1,81 @@
+package de.ugoe.cs.quest.usability;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTree;
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 16.07.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public class UsabilityEvaluationManager {
+    
+    /** */
+    private List<UsabilityEvaluationRule> rules = new ArrayList<UsabilityEvaluationRule>();
+
+    /**
+     * TODO: comment
+     * 
+     */
+    public UsabilityEvaluationManager() {
+        super();
+        init();
+    }
+
+    /**
+     * TODO: comment
+     * 
+     */
+    private void init() {
+        rules.add(new TextInputStatisticsRule());
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param taskTree
+     */
+    public UsabilityEvaluationResult evaluateUsability(ITaskTree taskTree) {
+        Console.traceln(Level.INFO, "evaluating usability of task tree " + taskTree);
+
+        List<UsabilityEvaluationResult> results = new ArrayList<UsabilityEvaluationResult>();
+
+        for (UsabilityEvaluationRule rule : rules) {
+            Console.traceln(Level.INFO, "applying rule " + rule.getClass().getSimpleName());
+            UsabilityEvaluationResult result = rule.evaluate(taskTree);
+            results.add(result);
+            Console.traceln(Level.INFO, "the rule found " + result.getAllDefects().size() +
+                            " usability defects, of which " + result.getSevereDefects().size() +
+                            " are severe.");
+        }
+
+        UsabilityEvaluationResult result = mergeResults(results);
+        Console.println("the evaluation result contains " + result.getAllDefects().size() +
+                        " defects, of which " + result.getSevereDefects().size() + " are severe.");
+        return result;
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param results
+     * @return
+     */
+    private UsabilityEvaluationResult mergeResults(List<UsabilityEvaluationResult> results) {
+        UsabilityEvaluationResult result = new UsabilityEvaluationResult();
+
+        for (UsabilityEvaluationResult ruleResult : results) {
+            for (UsabilityDefect defect : ruleResult.getAllDefects()) {
+                result.addDefect(defect);
+            }
+        }
+
+        return result;
+    }
+
+}
Index: /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/UsabilityEvaluationResult.java
===================================================================
--- /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/UsabilityEvaluationResult.java	(revision 896)
+++ /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/UsabilityEvaluationResult.java	(revision 896)
@@ -0,0 +1,52 @@
+package de.ugoe.cs.quest.usability;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 16.07.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public class UsabilityEvaluationResult {
+    
+    /** */
+    private List<UsabilityDefect> defects = new ArrayList<UsabilityDefect>();
+
+    /**
+     * TODO: comment
+     * 
+     * @param defect
+     */
+    public void addDefect(UsabilityDefect defect) {
+        defects.add(defect);
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @return
+     */
+    public List<UsabilityDefect> getAllDefects() {
+        return defects;
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @return
+     */
+    public List<UsabilityDefect> getSevereDefects() {
+        List<UsabilityDefect> severeDefects = new ArrayList<UsabilityDefect>();
+
+        for (UsabilityDefect defect : defects) {
+            if (defect.getSeverity() == UsabilityDefectSeverity.HIGH) {
+                severeDefects.add(defect);
+            }
+        }
+
+        return severeDefects;
+    }
+
+}
Index: /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/UsabilityEvaluationRule.java
===================================================================
--- /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/UsabilityEvaluationRule.java	(revision 896)
+++ /trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/quest/usability/UsabilityEvaluationRule.java	(revision 896)
@@ -0,0 +1,21 @@
+package de.ugoe.cs.quest.usability;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTree;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 16.07.2012$
+ * @author 2012, last modified by $Author: pharms$
+ */
+public interface UsabilityEvaluationRule {
+
+    /**
+     * TODO: comment
+     * 
+     * @param taskTree
+     * @return
+     */
+    UsabilityEvaluationResult evaluate(ITaskTree taskTree);
+
+}
Index: /trunk/autoquest-core-usability/src/main/resources/defectDescriptions.xsd
===================================================================
--- /trunk/autoquest-core-usability/src/main/resources/defectDescriptions.xsd	(revision 896)
+++ /trunk/autoquest-core-usability/src/main/resources/defectDescriptions.xsd	(revision 896)
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsd:schema
+  targetNamespace="http://quest"
+  xmlns:tns="http://quest"
+  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+  xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
+  jxb:version="2.0"
+  elementFormDefault="qualified">
+  
+  <xsd:element name="defectDescriptions" type="tns:DefectDescriptions" />
+
+  <xsd:complexType name="DefectDescriptions">
+    <xsd:sequence>
+      <xsd:element name="defectDescription" type="tns:DefectDescription" maxOccurs="unbounded" />
+    </xsd:sequence>
+  </xsd:complexType>
+
+  <xsd:complexType name="DefectDescription">
+    <xsd:choice maxOccurs="unbounded">
+      <xsd:element name="textFragment" type="tns:SimpleFragment" />
+      <xsd:element name="parameterFragment" type="tns:ParameterFragment" />
+    </xsd:choice>
+    <xsd:attribute name="defectId" type="xsd:string" use="required" />
+  </xsd:complexType>
+
+  <xsd:simpleType name="SimpleFragment">
+    <xsd:restriction base="xsd:string"/>
+  </xsd:simpleType>
+
+  <xsd:complexType name="ParameterFragment">
+    <xsd:attribute name="parameterName" use="required" type="xsd:string" />
+  </xsd:complexType>
+
+</xsd:schema>
Index: /trunk/autoquest-core-usability/src/main/resources/defectDescriptions_en.xml
===================================================================
--- /trunk/autoquest-core-usability/src/main/resources/defectDescriptions_en.xml	(revision 896)
+++ /trunk/autoquest-core-usability/src/main/resources/defectDescriptions_en.xml	(revision 896)
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<defectDescriptions
+  xmlns="http://quest"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://quest defectDescriptions.xsd">
+  
+  <defectDescription defectId="TEXT_FIELD_INPUT_RATIO">
+    <textFragment>
+      The ratio of interactions that enter text into text fields is relatively high in comparison
+      with the other user interactions (
+    </textFragment>
+    <parameterFragment parameterName="textInputRatio" />
+    <textFragment>
+      ). This should be reduced. As an example, entering data can also be done using check boxes
+      or combo boxes in the case predefined values must be entered.
+    </textFragment>
+  </defectDescription>
+  
+  <defectDescription defectId="TEXT_FIELD_INPUT_REPETITIONS">
+    <textFragment>
+      Several interactions that enter text into text fields repeat tokens such as words or
+      specific signs (
+    </textFragment>
+    <parameterFragment parameterName="textRepetitionRatio" />
+    <textFragment>
+      ). This is an indicator that the same data must be entered several times. This could be
+      better supported by using e.g. automatic filling of input fields, provision of combo
+      boxes or lists prefilled with data that was already entered previously. 
+    </textFragment>
+  </defectDescription>
+  
+  <defectDescription defectId="TEXT_FIELD_NO_LETTER_OR_DIGIT_RATIO">
+    <textFragment>
+      Much of the text entered into text fields contains signs other than letters or digits (
+    </textFragment>
+    <parameterFragment parameterName="noLetterOrDigitRatio" />
+    <textFragment>
+      ). This is an indicator that the entered data has to follow a specific syntax. This should
+      be supported by syntax checking, auto completion or even providing the text fields in a way
+      that does not require the entering of special signs as they are already included at the right
+      positions.
+    </textFragment>
+  </defectDescription>
+</defectDescriptions>
