Index: /trunk/autoquest-androidmonitor/.classpath
===================================================================
--- /trunk/autoquest-androidmonitor/.classpath	(revision 1833)
+++ /trunk/autoquest-androidmonitor/.classpath	(revision 1833)
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<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="me.gladwell.eclipse.m2e.android.classpath.NONRUNTIME_DEPENDENCIES">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" path="gen">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+	<classpathentry kind="src" output="bin/classes" path="src/main/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry exported="true" kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="bin/classes"/>
+</classpath>
Index: /trunk/autoquest-androidmonitor/.project
===================================================================
--- /trunk/autoquest-androidmonitor/.project	(revision 1833)
+++ /trunk/autoquest-androidmonitor/.project	(revision 1833)
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>autoquest-androidmonitor</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ApkBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+	</natures>
+</projectDescription>
Index: /trunk/autoquest-androidmonitor/.settings/org.eclipse.core.resources.prefs
===================================================================
--- /trunk/autoquest-androidmonitor/.settings/org.eclipse.core.resources.prefs	(revision 1833)
+++ /trunk/autoquest-androidmonitor/.settings/org.eclipse.core.resources.prefs	(revision 1833)
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding/<project>=UTF-8
Index: /trunk/autoquest-androidmonitor/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- /trunk/autoquest-androidmonitor/.settings/org.eclipse.jdt.core.prefs	(revision 1833)
+++ /trunk/autoquest-androidmonitor/.settings/org.eclipse.jdt.core.prefs	(revision 1833)
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.5
Index: /trunk/autoquest-androidmonitor/.settings/org.eclipse.m2e.core.prefs
===================================================================
--- /trunk/autoquest-androidmonitor/.settings/org.eclipse.m2e.core.prefs	(revision 1833)
+++ /trunk/autoquest-androidmonitor/.settings/org.eclipse.m2e.core.prefs	(revision 1833)
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
Index: /trunk/autoquest-androidmonitor/AndroidManifest.xml
===================================================================
--- /trunk/autoquest-androidmonitor/AndroidManifest.xml	(revision 1833)
+++ /trunk/autoquest-androidmonitor/AndroidManifest.xml	(revision 1833)
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="de.ugoe.cs.autoquest.androidmonitor"
+    android:versionCode="1"
+    android:versionName="0.1.2-SNAPSHOT"
+    android:allowBackup="true" >
+
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="16" />
+
+
+</manifest>
Index: /trunk/autoquest-androidmonitor/pom.xml
===================================================================
--- /trunk/autoquest-androidmonitor/pom.xml	(revision 1833)
+++ /trunk/autoquest-androidmonitor/pom.xml	(revision 1833)
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- Error Message: „Plugin execution not covered by lifecycle configuration: 
+	com.jayway.maven.plugins.android.generation2:android-maven-plugin:3.8.2:consume-aar 
+	(execution: default-consume-aar, phase: compile)“ can be ignored. 
+	RM ->Quick Fix-> Mark goal consume-aar as ignored in Eclipse build in Eclipse 
+	preferences (experimental) -> Finish 
+	As written on http://stackoverflow.com/questions/21016211/error-in-maven-pom-xml-file 
+	(2014-11-12) and http://wiki.eclipse.org/M2E_plugin_execution_not_covered 
+	(214-11-12) this is a known Problem and the error could be ignored. -->
+
+<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/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>de.ugoe.cs.autoquest</groupId>
+	<artifactId>autoquest-androidmonitor</artifactId>
+	<version>0.0.1-SNAPSHOT</version>
+	<packaging>apk</packaging>
+	<name>autoquest-androidmonitor</name>
+
+	<scm>
+		<url>https://autoquest.informatik.uni-goettingen.de/svn/autoquest/trunk/${project.artifactId}</url>
+		<connection>scm:svn:https://autoquest.informatik.uni-goettingen.de/svn/autoquest/trunk/${project.artifactId}</connection>
+	</scm>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<platform.version> 4.1.1.4
+		</platform.version>
+		<android.plugin.version>3.8.2</android.plugin.version>
+	</properties>
+
+	<distributionManagement>
+		<snapshotRepository>
+			<id>autoquest-snapshots</id>
+			<url>https://trex.informatik.uni-goettingen.de/nexus/content/repositories/autoquest-snapshots</url>
+		</snapshotRepository>
+		<repository>
+			<id>autoquest</id>
+			<url>https://trex.informatik.uni-goettingen.de/nexus/content/repositories/autoquest-releases</url>
+		</repository>
+	</distributionManagement>
+
+	<dependencies>
+		<dependency>
+			<groupId>com.google.android</groupId>
+			<artifactId>android</artifactId>
+			<version>${platform.version}</version>
+			<scope>provided</scope>
+		</dependency>
+	</dependencies>
+	<build>
+		<finalName>${project.artifactId}</finalName>
+		<pluginManagement>
+			<plugins>
+				<plugin>
+					<groupId>com.jayway.maven.plugins.android.generation2</groupId>
+					<artifactId>android-maven-plugin</artifactId>
+					<version>${android.plugin.version}</version>
+					<extensions>true</extensions>
+				</plugin>
+			</plugins>
+		</pluginManagement>
+		<plugins>
+
+			<plugin>
+				<groupId>com.jayway.maven.plugins.android.generation2</groupId>
+				<artifactId>android-maven-plugin</artifactId>
+				<configuration>
+					<sdk>
+						<platform>16</platform>
+					</sdk>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+</project>
Index: /trunk/autoquest-androidmonitor/project.properties
===================================================================
--- /trunk/autoquest-androidmonitor/project.properties	(revision 1833)
+++ /trunk/autoquest-androidmonitor/project.properties	(revision 1833)
@@ -0,0 +1,15 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-16
+android.library=true
Index: /trunk/autoquest-androidmonitor/res/layout/activity_main.xml
===================================================================
--- /trunk/autoquest-androidmonitor/res/layout/activity_main.xml	(revision 1833)
+++ /trunk/autoquest-androidmonitor/res/layout/activity_main.xml	(revision 1833)
@@ -0,0 +1,14 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingBottom="@dimen/activity_vertical_margin"
+    android:paddingLeft="@dimen/activity_horizontal_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingTop="@dimen/activity_vertical_margin" >
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/hello_world" />
+
+</RelativeLayout>
Index: /trunk/autoquest-androidmonitor/res/menu/main.xml
===================================================================
--- /trunk/autoquest-androidmonitor/res/menu/main.xml	(revision 1833)
+++ /trunk/autoquest-androidmonitor/res/menu/main.xml	(revision 1833)
@@ -0,0 +1,9 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item
+        android:id="@+id/action_settings"
+        android:orderInCategory="100"
+        android:showAsAction="never"
+        android:title="@string/action_settings"/>
+
+</menu>
Index: /trunk/autoquest-androidmonitor/res/values/dimens.xml
===================================================================
--- /trunk/autoquest-androidmonitor/res/values/dimens.xml	(revision 1833)
+++ /trunk/autoquest-androidmonitor/res/values/dimens.xml	(revision 1833)
@@ -0,0 +1,7 @@
+<resources>
+
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
Index: /trunk/autoquest-androidmonitor/res/values/strings.xml
===================================================================
--- /trunk/autoquest-androidmonitor/res/values/strings.xml	(revision 1833)
+++ /trunk/autoquest-androidmonitor/res/values/strings.xml	(revision 1833)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name">Maven Quickstart</string>
+    <string name="hello">Hello autoquest-androidmonitor!</string>
+    <string name="action_settings">Settings</string>
+    <string name="hello_world">Hello world!</string>
+
+</resources>
Index: /trunk/autoquest-androidmonitor/res/values/styles.xml
===================================================================
--- /trunk/autoquest-androidmonitor/res/values/styles.xml	(revision 1833)
+++ /trunk/autoquest-androidmonitor/res/values/styles.xml	(revision 1833)
@@ -0,0 +1,20 @@
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>
Index: /trunk/autoquest-androidmonitor/src/main/java/de/ugoe/cs/autoquest/androidmonitor/AndroidMonitor.java
===================================================================
--- /trunk/autoquest-androidmonitor/src/main/java/de/ugoe/cs/autoquest/androidmonitor/AndroidMonitor.java	(revision 1833)
+++ /trunk/autoquest-androidmonitor/src/main/java/de/ugoe/cs/autoquest/androidmonitor/AndroidMonitor.java	(revision 1833)
@@ -0,0 +1,302 @@
+//   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.androidmonitor;
+
+import java.lang.reflect.Field;
+
+import de.ugoe.cs.autoquest.androidmonitor.AndroidMonitorCompositeOnClickListener;
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Build;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+/**
+ * <p>
+ * Monitor an android activity. Call this class via
+ * AndroidMonitor.getInstanceOfAndroidMonitor().startMonitor(this); at the end of the
+ * onCreate(Bundle savedInstanceState) method.
+ * </p>
+ * 
+ * @author Florian Unger
+ * @version 1.0
+ */
+public class AndroidMonitor {
+
+    /**
+     * <p>
+     * Name of the Activity that starts the monitor.
+     * </p>
+     */
+    String activityName;
+
+    /**
+     * <p>
+     * Represents the operations to the log file.
+     * </p>
+     */
+    private AndroidMonitorLogFile logFile;
+
+    /**
+     * Constructor method to get a monitor object.
+     * 
+     * @return monitor
+     */
+    public static AndroidMonitor getInstanceOfAndroidMonitor() {
+        AndroidMonitor monitor = new AndroidMonitor();
+        return monitor;
+    }
+
+    /**
+     * starts tracking an activity
+     * 
+     * @param activity
+     */
+    public void startMonitor(Activity activity) {
+        activityName = activity.getClass().getSimpleName();
+
+        logFile = new AndroidMonitorLogFile(getAppLable(activity), activity.getFilesDir());
+
+        addLogListenerToView(getRootView(activity));
+
+        // TODO
+        // listen to changes and update own listener
+        // find out if it is possible to directly call addLogListenerToView
+        // again
+        // activity.onContentChanged();
+
+        // write backPresss as event to xml file
+        // activity.onBackPressed();
+
+        // handle onStop() method of the activity
+        // add a function that end up tracking if onStop() is given otherwise
+        // create onStop()
+        // http://developer.android.com/training/basics/activity-lifecycle/stopping.html
+    }
+
+    /**
+     * get the root view of an activity
+     * 
+     * @param activity
+     * @return
+     */
+    public View getRootView(Activity activity) {
+        // get root view of the activity as start point
+        View view = activity.getWindow().getDecorView().getRootView();
+        // try out if the given node is the upper one in the tree and return the
+        // first node of the tree
+        // The root of the decorView could be embedded into another layout
+        // element.
+        return findFirstView(view);
+    }
+
+    /**
+     * returns first view element of the tree
+     * 
+     * @param view
+     * @return
+     */
+    private View findFirstView(View view) {
+        if (view.getParent() != null && (view.getParent() instanceof ViewGroup)) {
+            return findFirstView((View) view.getParent());
+        }
+        else {
+            return view;
+        }
+    }
+
+    /**
+     * Replace the listener of each view with a composite listener which collects several listeners
+     * for one view.
+     * 
+     * @param view
+     *            to be monitored
+     */
+    public void addLogListenerToView(View view) {
+        addLogListenerToView(view, 0);
+    }
+
+    /**
+     * Replace the listener of each view with a composite listener which collects several listeners
+     * for one view.
+     * 
+     * @param view
+     *            to be monitored
+     * @param parentHash
+     *            hash of the parent view element
+     */
+    private void addLogListenerToView(View view, int parentHash) {
+
+        if (!logFile.isComponentLogged(view.hashCode())) {
+            logFile.addComponent(view, parentHash, activityName);
+        }
+
+        // hash code of the actual view element. Problem in using
+        // view.getParent().hashCode() is described in
+        // de.ugoe.cs.autoquest.androidmonitor#addComponent()
+        parentHash = view.hashCode();
+        // traverse all views of the activity
+        if (view instanceof ViewGroup) {
+            ViewGroup group = (ViewGroup) view;
+            for (int i = 0; i < group.getChildCount(); i++) {
+                View child = group.getChildAt(i);
+                addLogListenerToView(child, parentHash);
+            }
+        }
+
+        // save original listener to add it later on to the groupLisatener
+        View.OnClickListener onClickListener = getOnClickListener(view);
+
+        if (onClickListener != null) {
+            // create new compositeOnClickListener to handle multiple listeners
+            // for one view
+            AndroidMonitorCompositeOnClickListener groupListener =
+                new AndroidMonitorCompositeOnClickListener();
+            // replace the original onClickListener with the
+            // compositeOnClickListener
+            view.setOnClickListener(groupListener);
+            // add the tracking part as a several listener
+            groupListener.addOnClickListener(new View.OnClickListener() {
+                public void onClick(View v) {
+
+                    logFile.addEvent(v, "onClick");
+                }
+            });
+
+            groupListener.addOnClickListener(onClickListener);
+        }
+        // if view is a TextView add a addTextChangedListener to this view
+        if (view instanceof TextView) {
+            final int hashOfView = view.hashCode();
+            TextView textView = (TextView) view;
+            textView.addTextChangedListener(new TextWatcher() {
+                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+                    // do nothing
+                }
+
+                public void onTextChanged(CharSequence s, int start, int before, int count) {
+                    // do nothing
+                }
+
+                public void afterTextChanged(Editable s) {
+                    logFile.addEvent(hashOfView, "text", s.toString());
+                }
+
+            });
+        }
+    }
+
+    /**
+     * finds out if a listener exists
+     * 
+     * @param view
+     * @return the listener of the view or null if no listener exists
+     */
+    public View.OnClickListener getOnClickListener(View view) {
+        // http://stackoverflow.com/questions/11186960/getonclicklistener-in-android-views
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+            return getOnClickListenerV14(view);
+        }
+        else {
+            return getOnClickListenerV(view);
+        }
+    }
+
+    // Used for APIs lower than ICS (API 14)
+    private View.OnClickListener getOnClickListenerV(View view) {
+        View.OnClickListener retrievedListener = null;
+        String viewStr = "android.view.View";
+        Field field;
+
+        try {
+            field = Class.forName(viewStr).getDeclaredField("mOnClickListener");
+            retrievedListener = (View.OnClickListener) field.get(view);
+        }
+        catch (NoSuchFieldException ex) {
+            Log.e("Reflection", "No Such Field.");
+        }
+        catch (IllegalAccessException ex) {
+            Log.e("Reflection", "Illegal Access.");
+        }
+        catch (ClassNotFoundException ex) {
+            Log.e("Reflection", "Class Not Found.");
+        }
+
+        return retrievedListener;
+    }
+
+    // Used for new ListenerInfo class structure used beginning with API 14
+    // (ICS)
+    private View.OnClickListener getOnClickListenerV14(View view) {
+        View.OnClickListener retrievedListener = null;
+        String viewStr = "android.view.View";
+        String lInfoStr = "android.view.View$ListenerInfo";
+
+        try {
+            Field listenerField = Class.forName(viewStr).getDeclaredField("mListenerInfo");
+            Object listenerInfo = null;
+
+            if (listenerField != null) {
+                listenerField.setAccessible(true);
+                listenerInfo = listenerField.get(view);
+            }
+
+            Field clickListenerField = Class.forName(lInfoStr).getDeclaredField("mOnClickListener");
+
+            if (clickListenerField != null && listenerInfo != null) {
+                retrievedListener = (View.OnClickListener) clickListenerField.get(listenerInfo);
+            }
+        }
+        catch (NoSuchFieldException ex) {
+            Log.e("Reflection", "No Such Field.");
+        }
+        catch (IllegalAccessException ex) {
+            Log.e("Reflection", "Illegal Access.");
+        }
+        catch (ClassNotFoundException ex) {
+            Log.e("Reflection", "Class Not Found.");
+        }
+
+        return retrievedListener;
+    }
+
+    /**
+     * get application name as defined in Package Name
+     * 
+     * @param pContext
+     *            package context; could also be an activity
+     * @return app name
+     */
+    public String getAppLable(Context pContext) {
+        // source (2014-09-04):
+        // http://stackoverflow.com/questions/11229219/android-get-application-name-not-package-name
+        PackageManager lPackageManager = pContext.getPackageManager();
+        ApplicationInfo lApplicationInfo = null;
+        try {
+            lApplicationInfo =
+                lPackageManager.getApplicationInfo(pContext.getApplicationInfo().packageName, 0);
+        }
+        catch (final NameNotFoundException e) {}
+        return (String) (lApplicationInfo != null ? lPackageManager
+            .getApplicationLabel(lApplicationInfo) : "Unknown");
+    }
+}
Index: /trunk/autoquest-androidmonitor/src/main/java/de/ugoe/cs/autoquest/androidmonitor/AndroidMonitorCompositeOnClickListener.java
===================================================================
--- /trunk/autoquest-androidmonitor/src/main/java/de/ugoe/cs/autoquest/androidmonitor/AndroidMonitorCompositeOnClickListener.java	(revision 1833)
+++ /trunk/autoquest-androidmonitor/src/main/java/de/ugoe/cs/autoquest/androidmonitor/AndroidMonitorCompositeOnClickListener.java	(revision 1833)
@@ -0,0 +1,87 @@
+//   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.androidmonitor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.view.View;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @author Florian Unger
+ * @version 1.0
+ */
+public class AndroidMonitorCompositeOnClickListener implements
+        View.OnClickListener {
+
+    /**
+     * <p>
+     * Save all listeners which belongs to a single view in a list.
+     * </p>
+     */
+    private List<View.OnClickListener> listeners;
+
+    /**
+     * 
+     * <p>
+     * Constructor. Creates a new AndroidMonitorCompositeOnClickListener.
+     * </p>
+     *
+     */
+    public AndroidMonitorCompositeOnClickListener() {
+            listeners = new ArrayList<View.OnClickListener>();
+    }
+
+    /**
+     * <p>
+     * Add a listener to a single view.
+     * </p>
+     * 
+     * @param listener
+     */
+    public void addOnClickListener(View.OnClickListener listener) {
+            listeners.add(listener);
+    }
+    
+    /* (non-Javadoc)
+     * @see android.view.View.OnClickListener#onClick(android.view.View)
+     */
+    public void onClick(View v) {
+        for (View.OnClickListener listener : listeners) {
+            listener.onClick(v);
+        }       
+    }
+}
+
+/*
+* (non-Javadoc)
+* In Android it is not possible to have multiple onCliclListener for one view.
+* This is also stated in
+* http://books.google.de/books?id=bKo_1uED72EC&pg=PA178&lpg
+* =PA178&dq=android+setonclicklistener
+* +call+old+listener&source=bl&ots=g45T5ikRVK
+* &sig=blIqJGMywqJEGNATe3WW5DZyS6M&hl
+* =de&sa=X&ei=cl3rU6_8Ec2KOIzqgNgM&ved=0CEYQ6AEwBA
+* #v=onepage&q=android%20setonclicklistener%20call%20old%20listener&f=false
+* 
+* Therefore it is necessary to have a custom class to handle a single onClick()
+* and pass in handlers for it to call.
+* http://stackoverflow.com/questions/7587299
+* /android-multi-onclick-listener-in-one-button
+*/
Index: /trunk/autoquest-androidmonitor/src/main/java/de/ugoe/cs/autoquest/androidmonitor/AndroidMonitorLogFile.java
===================================================================
--- /trunk/autoquest-androidmonitor/src/main/java/de/ugoe/cs/autoquest/androidmonitor/AndroidMonitorLogFile.java	(revision 1833)
+++ /trunk/autoquest-androidmonitor/src/main/java/de/ugoe/cs/autoquest/androidmonitor/AndroidMonitorLogFile.java	(revision 1833)
@@ -0,0 +1,493 @@
+//   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.androidmonitor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.xmlpull.v1.XmlSerializer;
+
+import android.util.Log;
+import android.util.Xml;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @author Florian Unger
+ * @version 1.0
+ */
+public class AndroidMonitorLogFile {
+
+    /**
+     * <p>
+     * Name of the log file which is stored in the internal space of the device.
+     * </p>
+     */
+    private String name;
+    
+    /**
+     * <p>
+     * File representation to store monitored information. 
+     * </p>
+     */
+    private File file;
+    
+    /**
+     * <p>
+     * List representing all components which was written to log file before.
+     * </p>
+     */
+    private List<Integer> currentLoggedComponents;
+
+    /**
+     * 
+     * <p>
+     * Constructor. Creates a new AndroidmonitorLogFile.
+     * </p>
+     *
+     * @param appName
+     *          Name of the calling application.
+     * @param dir
+     *          Folder to store the log file.
+     */
+    public AndroidMonitorLogFile(String appName, File dir) {
+        
+        currentLoggedComponents = new ArrayList<Integer>();
+        
+        this.name = "androidLogFile_" + appName + System.currentTimeMillis() + ".log";
+
+        try {
+                // prove if file exists
+                this.file = new File(dir, this.name);
+                /*
+                 * if file does not exists write device and app information to a new
+                 * file. Otherwise use existing file and add activity information to
+                 * file.
+                 */
+                // TODO prove if file exists and add activity information
+                if (true) { // !this.file.exists()
+                        /*
+                         * create log file. Using method openFileOutput() does not work
+                         * for this project due to the reason that this method would try
+                         * to create the file in the directory of the non-existing
+                         * directory de.ugoe.cs.androidmonitor. This directory does not
+                         * exist due to the reason that this project is a library and
+                         * the file has to be stored in the directory of the running
+                         * application. Furthermore it would not be possible to write in
+                         * another app directory as the own one.
+                         */
+
+                        String string = "<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><sessions>";
+                        
+                        try {
+                                FileOutputStream outputStream = new FileOutputStream(
+                                                this.file);
+                                outputStream.write(string.getBytes());
+                                outputStream.close();
+                        } catch (Exception e) {
+                                Log.e("this.file", "outputstream: " + e.getMessage());
+                        }
+                        
+                        setDeviceInformation();
+                        setAppInformation();
+
+                } 
+                /*else {
+                        // TODO add activity information
+                }*/
+        } catch (Exception e) {
+                e.printStackTrace();
+                Log.e("file", "file: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 
+     * <p>
+     * Get file name which is in use.
+     * </p>
+     *
+     * @return filename
+     */
+    public String getFileName() {
+            return this.name;
+    }
+
+    /**
+     * 
+     * <p>
+     * Writes information about the application to the log file.
+     * </p>
+     *
+     */
+    private void setAppInformation() {
+            // TODO create app information in the same manner as coded in
+            // getDeviceInformation
+            
+    }
+
+    /**
+     * <p>
+     * Query device information and store it to log file.
+     * </p>
+     * 
+     */
+    private void setDeviceInformation() {
+           
+            XmlSerializer serializer = Xml.newSerializer();
+            StringWriter writer = new StringWriter();
+            try {
+                    serializer.setOutput(writer);
+                    serializer.startTag("", "device");
+                    serializer.startTag("", "param");
+                    serializer.attribute("", "value", ""
+                                    + android.os.Build.VERSION.SDK_INT);
+                    serializer.attribute("", "name", "sdk_version");
+                    serializer.endTag("", "param");
+
+                    serializer.startTag("", "param");
+                    serializer.attribute("", "value", android.os.Build.DEVICE);
+                    serializer.attribute("", "name", "device");
+                    serializer.endTag("", "param");
+
+                    serializer.startTag("", "param");
+                    serializer.attribute("", "value", android.os.Build.MANUFACTURER);
+                    serializer.attribute("", "name", "manufacturer");
+                    serializer.endTag("", "param");
+
+                    serializer.startTag("", "param");
+                    serializer.attribute("", "value", android.os.Build.MODEL);
+                    serializer.attribute("", "name", "model");
+                    serializer.endTag("", "param");
+
+                    // TODO get resolution ...
+
+                    serializer.endTag("", "device");
+                    serializer.endDocument();
+                    
+                    writeToFile(writer.toString());
+
+            } catch (IllegalArgumentException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+                Log.e("file", "outputstream: " + e.getMessage());
+            } catch (IllegalStateException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    Log.e("file", "outputstream: " + e.getMessage());
+            } catch (IOException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    Log.e("file", "outputstream: " + e.getMessage());
+            }
+
+            
+    }
+
+    /**
+     * <p>
+     * Adds some information of an component of an activity (view) to the file.
+     * </p>
+     * 
+     * @param view
+     *            view to be logged
+     * @param parentHash
+     *            hash of the parent view
+     * @param activityName
+     *            name of the activity that is analyzed
+     */
+    public void addComponent(View view, int parentHash, String activityName) {
+            XmlSerializer serializer = Xml.newSerializer();
+            StringWriter writer = new StringWriter();
+            
+            try {
+                    serializer.setOutput(writer);
+                    serializer.startTag("", "component");
+                    // TODO find a way in that the hash code is unique over time and
+                    // target
+                    /*
+                     * (non-Javadoc) view.getId() seems to be unique over time and
+                     * targets but there is a problem. In some cases there is no ID
+                     * (value: -1).
+                     */
+                    serializer.attribute("", "hash", "" + view.hashCode());
+                    
+
+                    serializer.startTag("", "param");
+                    serializer.attribute("", "name", "id");
+                    serializer.attribute("", "value", "" + view.getId());
+                    serializer.endTag("", "param");
+
+                    serializer.startTag("", "param");
+                    serializer.attribute("", "name", "path");
+                    serializer.attribute("", "value", activityName + "/"
+                                    + getViewPath(view) + view.getClass().getSimpleName());
+                    serializer.endTag("", "param");
+
+                    serializer.startTag("", "param");
+                    serializer.attribute("", "name", "class");
+                    serializer.attribute("", "value", view.getClass().getName());
+                    serializer.endTag("", "param");
+
+                    serializer.startTag("", "param");
+                    serializer.attribute("", "name", "parent");
+                    // Problem in using view.getParent().hashCode():
+                    // http://developer.android.com/reference/android/view/View.html#getParent()
+                    // tells: "... parent is a ViewParent and not necessarily a View."
+                    // ViewParent does not have a method hashCode(). Solution is done
+                    // add parentHash as parameter to method addComponent() and
+                    // Androidmonitor-> addLogListenerToView.
+                    serializer.attribute("", "value", "" + parentHash);
+                    serializer.endTag("", "param");
+
+                    // TODO add title e.g. android:text="Button"
+
+                    serializer.startTag("", "ancestors");
+                    
+                    Class<? extends Object> classobject = view.getClass();
+                    
+                    while((classobject != null)){
+                            serializer.startTag("", "ancestor");
+                            serializer.attribute("", "name", classobject.getName());
+                            serializer.endTag("", "ancestor");
+                            classobject = classobject.getSuperclass();
+                    }
+                    serializer.endTag("", "ancestors");
+
+                    serializer.endTag("", "component");
+                    serializer.endDocument();
+
+                    writeToFile(writer.toString());
+
+            } catch (IllegalArgumentException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    Log.e("file", "outputstream: " + e.getMessage());
+            } catch (IllegalStateException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    Log.e("file", "outputstream: " + e.getMessage());
+            } catch (IOException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    Log.e("file", "outputstream: " + e.getMessage());
+            }
+
+    }
+
+    /**
+     * <p>
+     * Add an event to the log file
+     * </p>
+     * 
+     * @param hash
+     *                      hash value of the calling view of the listener
+     * @param type
+     *                      the type of listener e.g. textView ...
+     * @param message
+     *                      message typed in
+     */
+    public void addEvent(int hash, String type, String message){
+            XmlSerializer serializer = Xml.newSerializer();
+            StringWriter writer = new StringWriter();
+
+            try {
+                    serializer.setOutput(writer);
+
+                    serializer.startTag("", "event");
+                    serializer.attribute("", "id", type);
+
+                    serializer.startTag("", "param");
+                    serializer.attribute("", "value", "" + hash);
+                    serializer.attribute("", "name", "source");
+                    serializer.endTag("", "param");
+                    
+                    serializer.startTag("", "param");
+                    serializer.attribute("", "value", message);
+                    serializer.attribute("", "name", "message");
+                    serializer.endTag("", "param");
+
+                    serializer.startTag("", "param");
+                    serializer.attribute("", "value", "" + System.currentTimeMillis());
+                    serializer.attribute("", "name", "timestamp");
+                    serializer.endTag("", "param");
+
+                    serializer.endTag("", "event");
+                    serializer.endDocument();
+
+                    writeToFile(writer.toString());
+            } catch (IllegalArgumentException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    Log.e("file", "outputstream: " + e.getMessage());
+            } catch (IllegalStateException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    Log.e("file", "outputstream: " + e.getMessage());
+            } catch (IOException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    Log.e("file", "outputstream: " + e.getMessage());
+            }
+    }
+    
+    /**
+     * <p>
+     * Add an event to the log file
+     * </p>
+     * 
+     * @param view
+     *            the calling view of the listener
+     * @param type
+     *            the type of listener e.g. onClick ...
+     */
+    public void addEvent(View view, String type) {
+
+            String x = "" + view.getX();
+            String y = "" + view.getY();
+
+            XmlSerializer serializer = Xml.newSerializer();
+            StringWriter writer = new StringWriter();
+
+            try {
+                    serializer.setOutput(writer);
+
+                    serializer.startTag("", "event");
+                    serializer.attribute("", "id", type);
+
+                    serializer.startTag("", "param");
+                    serializer.attribute("", "value", x);
+                    serializer.attribute("", "name", "X");
+                    serializer.endTag("", "param");
+
+                    serializer.startTag("", "param");
+                    serializer.attribute("", "value", y);
+                    serializer.attribute("", "name", "Y");
+                    serializer.endTag("", "param");
+
+                    serializer.startTag("", "param");
+                    serializer.attribute("", "value", "" + view.hashCode());
+                    serializer.attribute("", "name", "source");
+                    serializer.endTag("", "param");
+
+                    serializer.startTag("", "param");
+                    serializer.attribute("", "value", "" + System.currentTimeMillis());
+                    serializer.attribute("", "name", "timestamp");
+                    serializer.endTag("", "param");
+
+                    serializer.endTag("", "event");
+                    serializer.endDocument();
+
+                    writeToFile(writer.toString());
+            } catch (IllegalArgumentException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    Log.e("file", "outputstream: " + e.getMessage());
+            } catch (IllegalStateException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    Log.e("file", "outputstream: " + e.getMessage());
+            } catch (IOException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    Log.e("file", "outputstream: " + e.getMessage());
+            }
+    }
+
+    /**
+     * <p>
+     * Writes given information to the file. e.g. previous produced XML
+     * statements.
+     * </p>
+     * 
+     * @param data
+     *            content to add to the file
+     */
+    private void writeToFile(String data) {
+
+            FileOutputStream outputStream;
+            try {
+                    outputStream = new FileOutputStream(file, true);
+                    outputStream.write(data.getBytes());
+                    outputStream.close();
+            } catch (FileNotFoundException e) {
+                    e.printStackTrace();
+                    Log.e("file", "outputstream: " + e.getMessage());
+            } catch (IOException e) {
+                    e.printStackTrace();
+                    Log.e("file", "outputstream: " + e.getMessage());
+            }
+
+    }
+
+    /**
+     * <p>
+     * Generates the path of an view element.
+     * </p>
+     * 
+     * @param view
+     * @return path path to the element
+     */
+    private String getViewPath(View view) {
+            return getViewPath(view, null);
+    }
+
+    /**
+     * <p>
+     * Generates the path of an view element.
+     * </p>
+     * 
+     * @param view
+     * @param path
+     * @return path path to the element
+     */
+    private String getViewPath(View view, String path) {
+            if (path == null) {
+                    path = "";
+            } else {
+                    path = view.getClass().getSimpleName() + "/" + path;
+            }
+            if (view.getParent() != null && (view.getParent() instanceof ViewGroup)) {
+                    return getViewPath((View) view.getParent(), path);
+            } else {
+                    return path;
+            }
+    }
+    
+    /**
+     * 
+     * <p>
+     * Check whether a component is still written to log file.
+     * </p>
+     *
+     * @param hashCode
+     *          hash code of the view
+     * @return
+     */
+    public Boolean isComponentLogged(Integer hashCode){
+        return currentLoggedComponents.contains(hashCode);
+    }
+    
+    
+}
