auto import from //branches/cupcake_rel/...@138607
diff --git a/tools/signature-tools/Android.mk b/tools/signature-tools/Android.mk
new file mode 100644
index 0000000..cf9e053
--- /dev/null
+++ b/tools/signature-tools/Android.mk
@@ -0,0 +1,66 @@
+# Copyright (C) 2008 The Android Open Source Project
+#
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+# signature-tools java library
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under,src)
+LOCAL_JAVA_RESOURCE_DIRS := templates
+
+LOCAL_MODULE := signature-tools
+LOCAL_JAVA_LIBRARIES := dx dex-tools
+LOCAL_STATIC_JAVA_LIBRARIES := stringtemplate antlr-2.7.7
+LOCAL_CLASSPATH := $(HOST_JDK_TOOLS_JAR)
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+# prebuilt stringtemplate.jar
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_PREBUILT_JAVA_LIBRARIES := stringtemplate:lib/stringtemplate.jar
+
+include $(BUILD_HOST_PREBUILT)
+
+# prebuilt antlr-2.7.7.jar
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_PREBUILT_JAVA_LIBRARIES := antlr-2.7.7:lib/antlr-2.7.7.jar
+
+include $(BUILD_HOST_PREBUILT)
+
+# signature-tool script
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_PREBUILT_EXECUTABLES := sig
+include $(BUILD_HOST_PREBUILT)
+
+# signature-create script
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_PREBUILT_EXECUTABLES := sig-create
+include $(BUILD_HOST_PREBUILT)
+
+# signature-check script
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_PREBUILT_EXECUTABLES := sig-check
+include $(BUILD_HOST_PREBUILT)
diff --git a/tools/signature-tools/README.txt b/tools/signature-tools/README.txt
new file mode 100644
index 0000000..b4198b9
--- /dev/null
+++ b/tools/signature-tools/README.txt
@@ -0,0 +1,55 @@
+__signature-tools__
+
+This project contains the source code and tests for API signature comparison tools.
+It consists roughly of five parts:
+
+#Signature model : A generic model to represent the structure of an API
+
+#Converters      : A dex -> signature model converter (utilizing the dex-tools parser)
+                   A java source -> signature model converter (utilizing the doclet tools)
+
+#Delta model     : A model to represent differences between two signature models
+    
+#Comparator      : Put two signature models into the comparator and you get a delta model
+
+#Report engine   : Translates a delta model to a html output based on templates (utilizing the StringTemplate framework)
+
+
+Since this folder contains a .project file, it can be imported directly into eclipse as a java project.
+
+Feel free to improve!
+
+_Structure_
+
+dex.reader
+  |
+  src : source code
+  |  |
+  |	 signature :  the driver classes
+  |  		|
+  |     compare : the comparator code
+  |     |   |
+  |     |   model : the delta model
+  |     |
+  |     converter : the converters
+  |     |
+  |     io : common io interfaces
+  |     |   |
+  |     |   html : html report generator
+  |     |
+  |     model : signature model
+  |
+  test : source code of the test suite
+  |
+  templates : templates for html output generation
+  |
+  launches : eclipse launches for the tools
+  |
+  lib : required libraries
+  |
+  spec : various input files to try the tool 
+  |
+  README.txt : you are here
+  |
+  TODO.txt   : tasks which are still open
+ 
diff --git a/tools/signature-tools/TODO.txt b/tools/signature-tools/TODO.txt
new file mode 100644
index 0000000..fd20800
--- /dev/null
+++ b/tools/signature-tools/TODO.txt
@@ -0,0 +1,5 @@
+__Todo__
+
+Add more complex tests
+Add more spec
+Add "plugin system" to enable different loader / differ / report engines. This can be simple as register the class name of the available loaders in a property file
diff --git a/tools/signature-tools/lib/antlr-2.7.7.jar b/tools/signature-tools/lib/antlr-2.7.7.jar
new file mode 100644
index 0000000..5e5f14b
--- /dev/null
+++ b/tools/signature-tools/lib/antlr-2.7.7.jar
Binary files differ
diff --git a/tools/signature-tools/lib/stringtemplate.jar b/tools/signature-tools/lib/stringtemplate.jar
new file mode 100644
index 0000000..8e41531
--- /dev/null
+++ b/tools/signature-tools/lib/stringtemplate.jar
Binary files differ
diff --git a/tools/signature-tools/sig b/tools/signature-tools/sig
new file mode 100755
index 0000000..19b57fa
--- /dev/null
+++ b/tools/signature-tools/sig
@@ -0,0 +1,47 @@
+#!/bin/bash
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# 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.
+
+# Set up prog to be the path of this script, including following symlinks,
+# and set up progdir to be the fully-qualified pathname of its directory.
+
+prog="$0"
+while [ -h "${prog}" ]; do
+    newProg=`/bin/ls -ld "${prog}"`
+    newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
+    if expr "x${newProg}" : 'x/' >/dev/null; then
+        prog="${newProg}"
+    else
+        progdir=`dirname "${prog}"`
+        prog="${progdir}/${newProg}"
+    fi
+done
+oldwd=`pwd`
+progdir=`dirname "${prog}"`
+cd "${progdir}"
+progdir=`pwd`
+prog="${progdir}"/`basename "${prog}"`
+cd "${oldwd}"
+
+libdir=`dirname $progdir`/framework
+
+javaOpts=""
+while expr "x$1" : 'x-J' >/dev/null; do
+    opt=`expr "$1" : '-J\(.*\)'`
+    javaOpts="${javaOpts} -${opt}"
+    shift
+done
+
+exec java $javaOpts -classpath $libdir/signature-tools.jar:$libdir/dex-tools.jar:$libdir/stringtemplate.jar:$libdir/antlr-2.7.7.jar signature.Main "$@"
\ No newline at end of file
diff --git a/tools/signature-tools/sig-check b/tools/signature-tools/sig-check
new file mode 100755
index 0000000..0c1cbce
--- /dev/null
+++ b/tools/signature-tools/sig-check
@@ -0,0 +1,114 @@
+#!/bin/bash
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# 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.
+
+# Set up prog to be the path of this script, including following symlinks,
+# and set up progdir to be the fully-qualified pathname of its directory.
+
+prog="$0"
+while [ -h "${prog}" ]; do
+    newProg=`/bin/ls -ld "${prog}"`
+    newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
+    if expr "x${newProg}" : 'x/' >/dev/null; then
+        prog="${newProg}"
+    else
+        progdir=`dirname "${prog}"`
+        prog="${progdir}/${newProg}"
+    fi
+done
+oldwd=`pwd`
+progdir=`dirname "${prog}"`
+cd "${progdir}"
+progdir=`pwd`
+prog="${progdir}"/`basename "${prog}"`
+cd "${oldwd}"
+
+libdir=`dirname $progdir`/framework
+classpath=$libdir/signature-tools.jar:$libdir/dex-tools.jar:\
+$libdir/stringtemplate.jar:$libdir/antlr-2.7.7.jar
+
+javaOpts=""
+while expr "x$1" : 'x-J' >/dev/null; do
+    opt=`expr "$1" : '-J\(.*\)'`
+    javaOpts="${javaOpts} -${opt}"
+    shift
+done
+
+COREDEX=${ANDROID_PRODUCT_OUT}/../../common/obj/JAVA_LIBRARIES/core_intermediates/classes.dex
+
+if [ ! -f ${COREDEX} ]; then
+    echo ERROR: $COREDEX not found
+    exit -1;
+fi
+
+sig --compare \
+--from sig ${ANDROID_BUILD_TOP}/cts/tools/signature-tools/spec/android.spec \
+--name android cupcake reference \
+--to dex ${COREDEX} \
+--name Android 1.0 \(current build\) \
+--out ${ANDROID_BUILD_TOP}/out/delta \
+--packages \
+java.beans \
+java.io \
+java.lang \
+java.lang.annotation \
+java.lang.ref \
+java.lang.reflect \
+java.math \
+java.net \
+java.nio \
+java.nio.channels \
+java.nio.channels.spi \
+java.nio.charset \
+java.nio.charset.spi \
+java.security \
+java.security.acl \
+java.security.cert \
+java.security.interfaces \
+java.security.spec \
+java.sql \
+java.text \
+java.util \
+java.util.concurrent \
+java.util.concurrent.atomic \
+java.util.concurrent.locks \
+java.util.jar \
+java.util.logging \
+java.util.prefs \
+java.util.regex \
+java.util.zip \
+javax.crypto \
+javax.crypto.interfaces \
+javax.crypto.spec \
+javax.imageio \
+javax.imageio.event \
+javax.imageio.metadata \
+javax.imageio.plugins.bmp \
+javax.imageio.plugins.jpeg \
+javax.imageio.spi \
+javax.imageio.stream \
+javax.net \
+javax.net.ssl \
+javax.security.auth \
+javax.security.auth.callback \
+javax.security.auth.login \
+javax.security.auth.x500 \
+javax.security.cert \
+javax.sql \
+javax.xml.parsers \
+org.w3c.dom \
+org.xml.sax \
+org.xml.sax.ext \
+org.xml.sax.helpers
diff --git a/tools/signature-tools/sig-create b/tools/signature-tools/sig-create
new file mode 100755
index 0000000..4049e69
--- /dev/null
+++ b/tools/signature-tools/sig-create
@@ -0,0 +1,111 @@
+#!/bin/bash
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# 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.
+
+# Set up prog to be the path of this script, including following symlinks,
+# and set up progdir to be the fully-qualified pathname of its directory.
+
+prog="$0"
+while [ -h "${prog}" ]; do
+    newProg=`/bin/ls -ld "${prog}"`
+    newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
+    if expr "x${newProg}" : 'x/' >/dev/null; then
+        prog="${newProg}"
+    else
+        progdir=`dirname "${prog}"`
+        prog="${progdir}/${newProg}"
+    fi
+done
+oldwd=`pwd`
+progdir=`dirname "${prog}"`
+cd "${progdir}"
+progdir=`pwd`
+prog="${progdir}"/`basename "${prog}"`
+cd "${oldwd}"
+
+libdir=`dirname $progdir`/framework
+classpath=$libdir/signature-tools.jar:$libdir/dex-tools.jar:\
+$libdir/stringtemplate.jar:$libdir/antlr-2.7.7.jar
+
+javaOpts=""
+while expr "x$1" : 'x-J' >/dev/null; do
+    opt=`expr "$1" : '-J\(.*\)'`
+    javaOpts="${javaOpts} -${opt}"
+    shift
+done
+
+COREDEX=${ANDROID_PRODUCT_OUT}/../../common/obj/JAVA_LIBRARIES/core_intermediates/classes.dex
+
+if [ ! -f ${COREDEX} ]; then
+    echo ERROR: $COREDEX not found
+    exit -1;
+fi
+
+sig --create dex ${COREDEX} \
+--out ${ANDROID_BUILD_TOP}/out/dex \
+--name cts_dex_1.0.1 \
+--packages           \
+java.beans \
+java.io \
+java.lang \
+java.lang.annotation \
+java.lang.ref \
+java.lang.reflect \
+java.math \
+java.net \
+java.nio \
+java.nio.channels \
+java.nio.channels.spi \
+java.nio.charset \
+java.nio.charset.spi \
+java.security \
+java.security.acl \
+java.security.cert \
+java.security.interfaces \
+java.security.spec \
+java.sql \
+java.text \
+java.util \
+java.util.concurrent \
+java.util.concurrent.atomic \
+java.util.concurrent.locks \
+java.util.jar \
+java.util.logging \
+java.util.prefs \
+java.util.regex \
+java.util.zip \
+javax.crypto \
+javax.crypto.interfaces \
+javax.crypto.spec \
+javax.imageio \
+javax.imageio.event \
+javax.imageio.metadata \
+javax.imageio.plugins.bmp \
+javax.imageio.plugins.jpeg \
+javax.imageio.spi \
+javax.imageio.stream \
+javax.net \
+javax.net.ssl \
+javax.security.auth \
+javax.security.auth.callback \
+javax.security.auth.login \
+javax.security.auth.x500 \
+javax.security.cert \
+javax.sql \
+javax.xml.parsers \
+org.w3c.dom \
+org.xml.sax \
+org.xml.sax.ext \
+org.xml.sax.helpers
\ No newline at end of file
diff --git a/tools/signature-tools/spec/android.spec b/tools/signature-tools/spec/android.spec
new file mode 100644
index 0000000..fbbf53a
--- /dev/null
+++ b/tools/signature-tools/spec/android.spec
Binary files differ
diff --git a/tools/signature-tools/src/signature/Main.java b/tools/signature-tools/src/signature/Main.java
new file mode 100644
index 0000000..5b1c9ff
--- /dev/null
+++ b/tools/signature-tools/src/signature/Main.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature;
+
+/**
+ * The main entry point for the signature tool. If invoked with
+ * <code>--create</code> the call is delegated to
+ * {@link signature.converter.Main}. If invoked with <code>--compare</code> the
+ * call is delegated to {@link signature.compare.Main}.
+ * 
+ * @see signature.converter.Main
+ * @see signature.compare.Main
+ */
+public class Main {
+
+    private static final String USAGE_MESSAGE = "usage:\n"
+            + "  sig --create (doclet | dex) sourcefiles --out directory"
+            + " --name <name> --packages packageName{ packageName}\n"
+            + "  sig --compare --from=(doclet | dex | sig) <sourcefiles>"
+            + " --name <name> --to=(doclet | dex | sig) <sourcefiles>"
+            + " --name <name> --out directory"
+            + " --packages packageName{ packageName}\n  sig --help";
+
+    /**
+     * This class is uninstantiable.
+     */
+    private Main() {
+        // This space intentionally left blank.
+    }
+
+    /**
+     * Run!
+     */
+    public static void main(String[] args) {
+        boolean gotCmd = false;
+        boolean showUsage = false;
+
+        try {
+            for (int i = 0; i < args.length; i++) {
+                String arg = args[i];
+                if (arg.equals("--") || !arg.startsWith("--")) {
+                    gotCmd = false;
+                    showUsage = true;
+                    break;
+                }
+
+                gotCmd = true;
+                if (arg.equals("--create")) {
+                    signature.converter.Main.main(without(args, i));
+                    break;
+                } else if (arg.equals("--compare")) {
+                    signature.compare.Main.main(without(args, i));
+                    break;
+                } else if (arg.equals("--version")) {
+                    version();
+                    break;
+                } else if (arg.equals("--help")) {
+                    showUsage = true;
+                    break;
+                } else {
+                    gotCmd = false;
+                }
+            }
+        } catch (UsageException ex) {
+            showUsage = true;
+        } catch (RuntimeException ex) {
+            System.err.println("\nUNEXPECTED TOP-LEVEL EXCEPTION:");
+            ex.printStackTrace();
+            System.exit(2);
+        } catch (Throwable ex) {
+            System.err.println("\nUNEXPECTED TOP-LEVEL ERROR:");
+            ex.printStackTrace();
+            System.exit(3);
+        }
+
+        if (!gotCmd) {
+            System.err.println("error: no command specified");
+            showUsage = true;
+        }
+
+        if (showUsage) {
+            usage();
+            System.exit(1);
+        }
+    }
+
+    /**
+     * Prints the version message.
+     */
+    private static void version() {
+        System.err.println("android sigtools version " + Version.VERSION);
+        System.exit(0);
+    }
+
+    /**
+     * Prints the usage message.
+     */
+    private static void usage() {
+        System.err.println(USAGE_MESSAGE);
+    }
+
+    /**
+     * Returns a copy of the given argument array, but without the indicated
+     * element.
+     * 
+     * @param orig
+     *            non-null; original array
+     * @param n
+     *            which element to omit
+     * @return non-null; new array
+     */
+    private static String[] without(String[] orig, int n) {
+        int len = orig.length - 1;
+        String[] newa = new String[len];
+        System.arraycopy(orig, 0, newa, 0, n);
+        System.arraycopy(orig, n + 1, newa, n, len - n);
+        return newa;
+    }
+
+}
diff --git a/tools/signature-tools/src/signature/UsageException.java b/tools/signature-tools/src/signature/UsageException.java
new file mode 100644
index 0000000..6cdf9cf
--- /dev/null
+++ b/tools/signature-tools/src/signature/UsageException.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature;
+
+/**
+ * Simple exception class used to communicate that the command-line tool should
+ * print the usage message.
+ */
+@SuppressWarnings("serial")
+public class UsageException extends RuntimeException {
+    // This space intentionally left blank.
+}
diff --git a/tools/signature-tools/src/signature/Version.java b/tools/signature-tools/src/signature/Version.java
new file mode 100644
index 0000000..d20e81f
--- /dev/null
+++ b/tools/signature-tools/src/signature/Version.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature;
+
+/**
+ * {@code Version} defines the VERSION constant of the signature tools.
+ */
+public class Version {
+    /**
+     * The program version of the signature tools.
+     */
+    public static final String VERSION = "0.1";
+}
diff --git a/tools/signature-tools/src/signature/compare/ApiComparator.java b/tools/signature-tools/src/signature/compare/ApiComparator.java
new file mode 100644
index 0000000..9232d2d
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/ApiComparator.java
@@ -0,0 +1,1705 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare;
+
+import signature.compare.model.IAnnotationDelta;
+import signature.compare.model.IAnnotationElementDelta;
+import signature.compare.model.IAnnotationFieldDelta;
+import signature.compare.model.IApiDelta;
+import signature.compare.model.IClassDefinitionDelta;
+import signature.compare.model.IConstructorDelta;
+import signature.compare.model.IDelta;
+import signature.compare.model.IEnumConstantDelta;
+import signature.compare.model.IFieldDelta;
+import signature.compare.model.IGenericDeclarationDelta;
+import signature.compare.model.IMethodDelta;
+import signature.compare.model.IModifierDelta;
+import signature.compare.model.IPackageDelta;
+import signature.compare.model.IParameterDelta;
+import signature.compare.model.IParameterizedTypeDelta;
+import signature.compare.model.IPrimitiveTypeDelta;
+import signature.compare.model.ITypeReferenceDelta;
+import signature.compare.model.ITypeVariableDefinitionDelta;
+import signature.compare.model.IUpperBoundsDelta;
+import signature.compare.model.IValueDelta;
+import signature.compare.model.IWildcardTypeDelta;
+import signature.compare.model.impl.SigAnnotationDelta;
+import signature.compare.model.impl.SigAnnotationElementDelta;
+import signature.compare.model.impl.SigAnnotationFieldDelta;
+import signature.compare.model.impl.SigApiDelta;
+import signature.compare.model.impl.SigArrayTypeDelta;
+import signature.compare.model.impl.SigClassDefinitionDelta;
+import signature.compare.model.impl.SigClassReferenceDelta;
+import signature.compare.model.impl.SigConstructorDelta;
+import signature.compare.model.impl.SigEnumConstantDelta;
+import signature.compare.model.impl.SigFieldDelta;
+import signature.compare.model.impl.SigGenericDeclarationDelta;
+import signature.compare.model.impl.SigMethodDelta;
+import signature.compare.model.impl.SigModifierDelta;
+import signature.compare.model.impl.SigPackageDelta;
+import signature.compare.model.impl.SigParameterDelta;
+import signature.compare.model.impl.SigParameterizedTypeDelta;
+import signature.compare.model.impl.SigPrimitiveTypeDelta;
+import signature.compare.model.impl.SigTypeDelta;
+import signature.compare.model.impl.SigTypeVariableDefinitionDelta;
+import signature.compare.model.impl.SigTypeVariableReferenceDelta;
+import signature.compare.model.impl.SigUpperBoundsDelta;
+import signature.compare.model.impl.SigValueDelta;
+import signature.compare.model.impl.SigWildcardTypeDelta;
+import signature.compare.model.subst.ClassProjection;
+import signature.compare.model.subst.ViewpointAdapter;
+import signature.model.IAnnotation;
+import signature.model.IAnnotationElement;
+import signature.model.IAnnotationField;
+import signature.model.IApi;
+import signature.model.IArrayType;
+import signature.model.IClassDefinition;
+import signature.model.IClassReference;
+import signature.model.IConstructor;
+import signature.model.IEnumConstant;
+import signature.model.IExecutableMember;
+import signature.model.IField;
+import signature.model.IGenericDeclaration;
+import signature.model.IMethod;
+import signature.model.IPackage;
+import signature.model.IParameter;
+import signature.model.IParameterizedType;
+import signature.model.IPrimitiveType;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+import signature.model.ITypeVariableReference;
+import signature.model.IWildcardType;
+import signature.model.Kind;
+import signature.model.Modifier;
+import signature.model.impl.SigAnnotationElement;
+import signature.model.impl.SigArrayType;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * {@code ApiComparator} takes two signature models as input and creates a delta
+ * model describing the differences between those.
+ */
+public class ApiComparator implements IApiComparator {
+
+    public IApiDelta compare(IApi from, IApi to) {
+        assert from.getVisibility() == to.getVisibility();
+
+        Set<IPackage> fromPackages = from.getPackages();
+        Set<IPackage> toPackages = to.getPackages();
+
+        Set<IPackageDelta> packageDeltas = compareSets(fromPackages,
+                toPackages, new SigComparator<IPackage, IPackageDelta>() {
+                    public IPackageDelta createChangedDelta(IPackage from,
+                            IPackage to) {
+                        return comparePackage(from, to);
+                    }
+
+                    public IPackageDelta createAddRemoveDelta(IPackage from,
+                            IPackage to) {
+                        return new SigPackageDelta(from, to);
+                    }
+
+                    public boolean considerEqualElement(IPackage from,
+                            IPackage to) {
+                        return from.getName().equals(to.getName());
+                    }
+                });
+
+        SigApiDelta delta = null;
+        if (packageDeltas != null) {
+            delta = new SigApiDelta(from, to);
+            delta.setPackageDeltas(packageDeltas);
+        }
+        return delta;
+    }
+
+    private IPackageDelta comparePackage(IPackage from, IPackage to) {
+        assert from.getName().equals(to.getName());
+
+        Set<IClassDefinition> fromClasses = from.getClasses();
+        Set<IClassDefinition> toClasses = to.getClasses();
+
+        Set<IClassDefinitionDelta> classDeltas = compareSets(fromClasses,
+                toClasses,
+                new SigComparator<IClassDefinition, IClassDefinitionDelta>() {
+                    public boolean considerEqualElement(IClassDefinition from,
+                            IClassDefinition to) {
+                        return sameClassDefinition(from, to);
+                    }
+
+                    public IClassDefinitionDelta createChangedDelta(
+                            IClassDefinition from, IClassDefinition to) {
+                        return compareClass(from, to);
+                    }
+
+                    public IClassDefinitionDelta createAddRemoveDelta(
+                            IClassDefinition from, IClassDefinition to) {
+                        return new SigClassDefinitionDelta(from, to);
+                    }
+                });
+
+        SigPackageDelta delta = null;
+        if (classDeltas != null) {
+            delta = new SigPackageDelta(from, to);
+            delta.setClassDeltas(classDeltas);
+        }
+
+        // Annotations
+        Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from
+                .getAnnotations(), to.getAnnotations());
+        if (annotationDeltas != null) {
+            if (delta != null) {
+                delta = new SigPackageDelta(from, to);
+            }
+            delta.setAnnotationDeltas(annotationDeltas);
+        }
+        return delta;
+    }
+
+    private IClassDefinitionDelta compareClass(IClassDefinition from,
+            IClassDefinition to) {
+        assert from.getKind() == to.getKind();
+        assert from.getName().equals(to.getName());
+        assert from.getPackageName().equals(to.getPackageName());
+
+        SigClassDefinitionDelta classDelta = null;
+
+        // modifiers
+        Set<IModifierDelta> modifierDeltas = compareModifiers(from
+                .getModifiers(), to.getModifiers());
+        if (modifierDeltas != null) {
+            if (classDelta == null) {
+                classDelta = new SigClassDefinitionDelta(from, to);
+            }
+            classDelta.setModifierDeltas(modifierDeltas);
+        }
+
+        // super class
+        ITypeReferenceDelta<?> superTypeDelta = compareType(from
+                .getSuperClass(), to.getSuperClass(), false);
+        if (superTypeDelta != null) {
+            if (classDelta == null) {
+                classDelta = new SigClassDefinitionDelta(from, to);
+            }
+            classDelta.setSuperClassDelta(superTypeDelta);
+        }
+
+        // interfaces
+        Set<ITypeReferenceDelta<?>> interfaceDeltas = compareInterfaces(from,
+                to);
+        if (interfaceDeltas != null) {
+            if (classDelta == null) {
+                classDelta = new SigClassDefinitionDelta(from, to);
+            }
+            classDelta.setInterfaceDeltas(interfaceDeltas);
+        }
+
+        // type variables
+        Set<ITypeVariableDefinitionDelta> typeVariableDeltas =
+                compareTypeVariableSequence(from.getTypeParameters(),
+                        to.getTypeParameters());
+        if (typeVariableDeltas != null) {
+            if (classDelta == null) {
+                classDelta = new SigClassDefinitionDelta(from, to);
+            }
+            classDelta.setTypeVariableDeltas(typeVariableDeltas);
+        }
+
+        // constructors
+        Set<IConstructorDelta> constructorDeltas = compareConstructors(from
+                .getConstructors(), to.getConstructors());
+        if (constructorDeltas != null) {
+            if (classDelta == null) {
+                classDelta = new SigClassDefinitionDelta(from, to);
+            }
+            classDelta.setConstructorDeltas(constructorDeltas);
+        }
+
+        // methods
+        Set<IMethodDelta> methodDeltas = compareMethods(from, to);
+        if (methodDeltas != null) {
+            if (classDelta == null) {
+                classDelta = new SigClassDefinitionDelta(from, to);
+            }
+            classDelta.setMethodDeltas(methodDeltas);
+        }
+
+        // fields
+        Set<IFieldDelta> fieldDeltas = compareFields(from.getFields(), to
+                .getFields());
+        if (fieldDeltas != null) {
+            if (classDelta == null) {
+                classDelta = new SigClassDefinitionDelta(from, to);
+            }
+            classDelta.setFieldDeltas(fieldDeltas);
+        }
+
+        // enum constants
+        if (from.getKind() == Kind.ENUM) {
+            Set<IEnumConstantDelta> enumDeltas = compareEnumConstants(from
+                    .getEnumConstants(), to.getEnumConstants());
+            if (enumDeltas != null) {
+                if (classDelta == null) {
+                    classDelta = new SigClassDefinitionDelta(from, to);
+                }
+                classDelta.setEnumConstantDeltas(enumDeltas);
+            }
+        } else if (from.getKind() == Kind.ANNOTATION) {
+            Set<IAnnotationFieldDelta> annotationFieldDeltas =
+                    compareAnnotationFields(from.getAnnotationFields(),
+                            to.getAnnotationFields());
+            if (annotationFieldDeltas != null) {
+                if (classDelta == null) {
+                    classDelta = new SigClassDefinitionDelta(from, to);
+                }
+                classDelta.setAnnotationFieldDeltas(annotationFieldDeltas);
+            }
+        }
+
+        Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from
+                .getAnnotations(), to.getAnnotations());
+        if (annotationDeltas != null) {
+            if (classDelta == null) {
+                classDelta = new SigClassDefinitionDelta(from, to);
+            }
+            classDelta.setAnnotationDeltas(annotationDeltas);
+        }
+        return classDelta;
+    }
+
+    private Set<ITypeReferenceDelta<?>> compareInterfaces(
+            IClassDefinition from, IClassDefinition to) {
+        Set<ITypeReference> fromClosure = getInterfaceClosure(from);
+        Set<ITypeReference> toClosure = getInterfaceClosure(to);
+
+        Set<ITypeReference> fromInterfaces = from.getInterfaces();
+        Set<ITypeReference> toInterfaces = to.getInterfaces();
+
+        Set<ITypeReferenceDelta<?>> deltas =
+                new HashSet<ITypeReferenceDelta<?>>();
+
+        // check whether all from interfaces are directly or indirectly
+        // implemented by the to method
+        for (ITypeReference type : fromInterfaces) {
+            if (!containsType(type, toInterfaces)) {
+                if (!(containsType(type, toClosure) /*
+                                                     * && !containsType(type,
+                                                     * toInterfaces)
+                                                     */)) {
+                    deltas.add(new SigTypeDelta<ITypeReference>(type, null));
+                }
+            }
+        }
+
+        // check whether all interfaces to are directly or indirectly
+        // implemented by the from method
+        for (ITypeReference type : toInterfaces) {
+            if (!containsType(type, fromInterfaces)) {
+                if (!(containsType(type, fromClosure) /*
+                                                       * && !containsType(type,
+                                                       * fromInterfaces)
+                                                       */)) {
+                    deltas.add(new SigTypeDelta<ITypeReference>(null, type));
+                }
+            }
+        }
+        return deltas.isEmpty() ? null : deltas;
+    }
+
+
+    private boolean containsType(ITypeReference type,
+            Set<ITypeReference> setOfTypes) {
+        for (ITypeReference other : setOfTypes) {
+            if (compareType(type, other, false) == null) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private Set<ITypeReference> getInterfaceClosure(IClassDefinition clazz) {
+        Set<ITypeReference> closure = new HashSet<ITypeReference>();
+        collectInterfaceClosure(ViewpointAdapter.getReferenceTo(clazz),
+                closure);
+        return closure;
+    }
+
+    private void collectInterfaceClosure(ITypeReference clazz,
+            Set<ITypeReference> closure) {
+
+        IClassDefinition classDefinition = getClassDefinition(clazz);
+        Set<ITypeReference> interfaces = classDefinition.getInterfaces();
+        if (interfaces == null) {
+            return;
+        }
+        for (ITypeReference interfaze : interfaces) {
+            closure.add(interfaze);
+        }
+
+        ITypeReference superclass = classDefinition.getSuperClass();
+        if (superclass != null) {
+            if (superclass instanceof IParameterizedType) {
+                collectInterfaceClosure(((IParameterizedType) superclass)
+                        .getRawType(), closure);
+            } else {
+                collectInterfaceClosure(superclass, closure);
+            }
+        }
+        for (ITypeReference interfaze : interfaces) {
+            if (interfaze instanceof IParameterizedType) {
+                collectInterfaceClosure(((IParameterizedType) interfaze)
+                        .getRawType(), closure);
+            } else {
+                collectInterfaceClosure(interfaze, closure);
+            }
+        }
+    }
+
+    private Set<IAnnotationDelta> compareAnnotations(Set<IAnnotation> from,
+            Set<IAnnotation> to) {
+        return compareSets(from, to,
+                new SigComparator<IAnnotation, IAnnotationDelta>() {
+                    public IAnnotationDelta createAddRemoveDelta(
+                            IAnnotation from, IAnnotation to) {
+                        return new SigAnnotationDelta(from, to);
+                    }
+
+                    public boolean considerEqualElement(IAnnotation from,
+                            IAnnotation to) {
+                        return sameClassDefinition(from.getType()
+                                .getClassDefinition(), to.getType()
+                                .getClassDefinition());
+                    }
+
+                    public IAnnotationDelta createChangedDelta(
+                            IAnnotation from, IAnnotation to) {
+                        return compareAnnotation(from, to);
+                    }
+                });
+    }
+
+    private Set<IAnnotationFieldDelta> compareAnnotationFields(
+            Set<IAnnotationField> from, Set<IAnnotationField> to) {
+        return compareSets(from, to,
+                new SigComparator<IAnnotationField, IAnnotationFieldDelta>() {
+                    public boolean considerEqualElement(IAnnotationField from,
+                            IAnnotationField to) {
+                        return from.getName().equals(to.getName());
+                    }
+
+                    public IAnnotationFieldDelta createAddRemoveDelta(
+                            IAnnotationField from, IAnnotationField to) {
+                        return new SigAnnotationFieldDelta(from, to);
+                    }
+
+                    public IAnnotationFieldDelta createChangedDelta(
+                            IAnnotationField from, IAnnotationField to) {
+                        return compareAnnotationField(from, to);
+                    }
+                });
+    }
+
+    private Set<IEnumConstantDelta> compareEnumConstants(
+            Set<IEnumConstant> from, Set<IEnumConstant> to) {
+        return compareSets(from, to,
+                new SigComparator<IEnumConstant, IEnumConstantDelta>() {
+                    public boolean considerEqualElement(IEnumConstant from,
+                            IEnumConstant to) {
+                        return from.getName().equals(to.getName());
+                    }
+
+                    public IEnumConstantDelta createAddRemoveDelta(
+                            IEnumConstant from, IEnumConstant to) {
+                        return new SigEnumConstantDelta(from, to);
+                    }
+
+                    public IEnumConstantDelta createChangedDelta(
+                            IEnumConstant from, IEnumConstant to) {
+                        return compareEnumConstant(from, to);
+                    }
+                });
+    }
+
+    private Set<IFieldDelta> compareFields(Set<IField> from, Set<IField> to) {
+        return compareSets(from, to, new SigComparator<IField, IFieldDelta>() {
+            public boolean considerEqualElement(IField from, IField to) {
+                return from.getName().equals(to.getName());
+            }
+
+            public IFieldDelta createAddRemoveDelta(IField from, IField to) {
+                return new SigFieldDelta(from, to);
+            }
+
+            public IFieldDelta createChangedDelta(IField from, IField to) {
+                return compareField(from, to);
+            }
+        });
+    }
+
+    private Set<IMethodDelta> compareMethods(IClassDefinition from,
+            IClassDefinition to) {
+        assert from != null;
+        assert to != null;
+
+        Set<IMethod> toMethods = new HashSet<IMethod>(to.getMethods());
+        Set<IMethod> toClosure = getMethodClosure(to);
+        Set<IMethod> fromMethods = new HashSet<IMethod>(from.getMethods());
+        Set<IMethod> fromClosure = getMethodClosure(from);
+
+        Set<IMethodDelta> deltas = new HashSet<IMethodDelta>();
+
+        for (IMethod method : fromMethods) {
+            IMethod compatibleMethod = findCompatibleMethod(method, toMethods);
+            if (compatibleMethod == null) {
+                compatibleMethod = findCompatibleMethod(method, toClosure);
+                if (compatibleMethod == null) {
+                    deltas.add(new SigMethodDelta(method, null));
+                }
+            }
+
+            if (compatibleMethod != null) {
+                IMethodDelta delta = compareMethod(method, compatibleMethod);
+                if (delta != null) {
+                    deltas.add(delta);
+                }
+            }
+        }
+
+        for (IMethod method : toMethods) {
+            IMethod compatibleMethod = findCompatibleMethod(method, fromMethods);
+            if (compatibleMethod == null) {
+                compatibleMethod = findCompatibleMethod(method, fromClosure);
+                if (compatibleMethod == null) {
+                    deltas.add(new SigMethodDelta(null, method));
+                }
+            }
+        }
+        return deltas.isEmpty() ? null : deltas;
+    }
+
+    private IMethod findCompatibleMethod(IMethod method, Set<IMethod> set) {
+        for (IMethod methodFromSet : set) {
+            if (equalsSignature(method, methodFromSet)) {
+                return methodFromSet;
+            }
+        }
+        return null;
+    }
+
+
+    private Set<IMethod> getMethodClosure(IClassDefinition clazz) {
+        Set<IMethod> closure = new HashSet<IMethod>();
+        collectMethods(new ClassProjection(clazz,
+                new HashMap<ITypeVariableDefinition, ITypeReference>()),
+                closure);
+        return closure;
+    }
+
+    private void collectMethods(IClassDefinition clazz, Set<IMethod> closure) {
+        if (clazz == null) {
+            return;
+        }
+        if (clazz.getMethods() != null) {
+            closure.addAll(clazz.getMethods());
+        }
+        if (clazz.getSuperClass() != null) {
+            collectMethods(getClassDefinition(clazz.getSuperClass()), closure);
+        }
+        if (clazz.getInterfaces() != null) {
+            for (ITypeReference interfaze : clazz.getInterfaces()) {
+                collectMethods(getClassDefinition(interfaze), closure);
+            }
+        }
+    }
+
+    private Set<IConstructorDelta> compareConstructors(Set<IConstructor> from,
+            Set<IConstructor> to) {
+        return compareSets(from, to,
+                new SigComparator<IConstructor, IConstructorDelta>() {
+                    public boolean considerEqualElement(IConstructor from,
+                            IConstructor to) {
+                        return equalsSignature(from, to);
+                    }
+
+                    public IConstructorDelta createAddRemoveDelta(
+                            IConstructor from, IConstructor to) {
+                        return new SigConstructorDelta(from, to);
+                    }
+
+                    public IConstructorDelta createChangedDelta(
+                            IConstructor from, IConstructor to) {
+                        return compareConstructor(from, to);
+                    }
+                });
+    }
+
+    // compares names and parameter types
+    private boolean equalsSignature(IExecutableMember from,
+            IExecutableMember to) {
+        if (from.getName().equals(to.getName())) {
+            return compareTypeSequence(getParameterList(from.getParameters()),
+                    getParameterList(to.getParameters()), true) == null;
+        }
+        return false;
+    }
+
+    private List<ITypeReference> getParameterList(List<IParameter> parameters) {
+        List<ITypeReference> parameterTypes = new LinkedList<ITypeReference>();
+        for (IParameter parameter : parameters) {
+            parameterTypes.add(parameter.getType());
+        }
+        return parameterTypes;
+    }
+
+    private IAnnotationDelta compareAnnotation(IAnnotation from,
+            IAnnotation to) {
+        assert sameClassDefinition(from.getType().getClassDefinition(), to
+                .getType().getClassDefinition());
+
+        Set<IAnnotationElement> fromAnnotationElement =
+                getNormalizedAnnotationElements(from);
+        Set<IAnnotationElement> toAnnotationElement =
+                getNormalizedAnnotationElements(to);
+
+        Set<IAnnotationElementDelta> annotationElementDeltas =
+                compareAnnotationElements(
+                        fromAnnotationElement, toAnnotationElement);
+        SigAnnotationDelta delta = null;
+
+        if (annotationElementDeltas != null) {
+            delta = new SigAnnotationDelta(from, to);
+            delta.setAnnotationElementDeltas(annotationElementDeltas);
+        }
+        return delta;
+    }
+
+    /**
+     * Returns the annotation elements for the given annotation. The returned
+     * set contains all declared elements plus all elements with default values.
+     * 
+     * @param annotation
+     *            the annotation to return the elements for
+     * @return the default enriched annotation elements
+     */
+    private Set<IAnnotationElement> getNormalizedAnnotationElements(
+            IAnnotation annotation) {
+        Set<IAnnotationElement> elements = new HashSet<IAnnotationElement>(
+                annotation.getElements());
+
+        Set<String> names = new HashSet<String>();
+        for (IAnnotationElement annotationElement : elements) {
+            names.add(annotationElement.getDeclaringField().getName());
+        }
+
+        for (IAnnotationField field : annotation.getType().getClassDefinition()
+                .getAnnotationFields()) {
+            if (!names.contains(field.getName())) {
+                SigAnnotationElement sigAnnotationElement =
+                        new SigAnnotationElement();
+                sigAnnotationElement.setDeclaringField(field);
+                sigAnnotationElement.setValue(field.getDefaultValue());
+                elements.add(sigAnnotationElement);
+            }
+        }
+        return elements;
+    }
+
+    private Set<IAnnotationElementDelta> compareAnnotationElements(
+            Set<IAnnotationElement> from, Set<IAnnotationElement> to) {
+        return compareSets(from, to,
+                new SigComparator<IAnnotationElement, IAnnotationElementDelta>() {
+                    public boolean considerEqualElement(
+                            IAnnotationElement from, IAnnotationElement to) {
+                        return from.getDeclaringField().getName().equals(
+                                to.getDeclaringField().getName());
+                    }
+
+                    public IAnnotationElementDelta createAddRemoveDelta(
+                            IAnnotationElement from, IAnnotationElement to) {
+                        return new SigAnnotationElementDelta(from, to);
+                    }
+
+                    public IAnnotationElementDelta createChangedDelta(
+                            IAnnotationElement from, IAnnotationElement to) {
+                        return compareAnnotationElement(from, to);
+                    }
+                });
+    }
+
+    private IAnnotationElementDelta compareAnnotationElement(
+            IAnnotationElement from, IAnnotationElement to) {
+        SigAnnotationElementDelta delta = null;
+        SigValueDelta valueDelta = compareValue(from.getValue(), to.getValue());
+
+        if (valueDelta != null) {
+            delta = new SigAnnotationElementDelta(from, to);
+            delta.setValueDelta(valueDelta);
+        }
+        return delta;
+    }
+
+    /**
+     * Removes the {@link Modifier#ABSTRACT} modifier.
+     */
+    private Set<Modifier> prepareMethodModifiers(IMethod method) {
+        Set<Modifier> modifierCopy = new HashSet<Modifier>(method
+                .getModifiers());
+        modifierCopy.remove(Modifier.ABSTRACT);
+        return modifierCopy;
+    }
+
+    private IMethodDelta compareMethod(IMethod from, IMethod to) {
+        assert from != null && to != null;
+
+        SigMethodDelta methodDelta = null;
+        Set<IModifierDelta> modiferDeltas = compareModifiers(
+                prepareMethodModifiers(from), prepareMethodModifiers(to));
+        if (modiferDeltas != null) {
+            methodDelta = new SigMethodDelta(from, to);
+            methodDelta.setModifierDeltas(modiferDeltas);
+        }
+
+        Set<IParameterDelta> parameterDeltas = compareParameterSequence(from
+                .getParameters(), to.getParameters());
+        if (parameterDeltas != null) {
+            if (methodDelta == null) {
+                methodDelta = new SigMethodDelta(from, to);
+            }
+            methodDelta.setParameterDeltas(parameterDeltas);
+        }
+
+        Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from
+                .getAnnotations(), to.getAnnotations());
+        if (annotationDeltas != null) {
+            if (methodDelta == null) {
+                methodDelta = new SigMethodDelta(from, to);
+            }
+            methodDelta.setAnnotationDeltas(annotationDeltas);
+        }
+
+        Set<ITypeVariableDefinitionDelta> typeParameterDeltas =
+                compareTypeVariableSequence(from.getTypeParameters(),
+                        to.getTypeParameters());
+        if (typeParameterDeltas != null) {
+            if (methodDelta == null) {
+                methodDelta = new SigMethodDelta(from, to);
+            }
+            methodDelta.setTypeVariableDeltas(typeParameterDeltas);
+        }
+
+        Set<ITypeReferenceDelta<?>> exceptionDeltas = compareTypes(
+                normalizeExceptions(from.getExceptions()),
+                normalizeExceptions(to.getExceptions()));
+        if (exceptionDeltas != null) {
+            if (methodDelta == null) {
+                methodDelta = new SigMethodDelta(from, to);
+            }
+            methodDelta.setExceptionDeltas(exceptionDeltas);
+        }
+
+        ITypeReferenceDelta<?> returnTypeDelta = compareType(from
+                .getReturnType(), to.getReturnType(), false);
+        if (returnTypeDelta != null) {
+            if (methodDelta == null) {
+                methodDelta = new SigMethodDelta(from, to);
+            }
+            methodDelta.setReturnTypeDelta(returnTypeDelta);
+        }
+
+        return methodDelta;
+    }
+
+    // remove runtime exceptions,
+    // remove sub types of containing exception
+    private Set<ITypeReference> normalizeExceptions(
+            Set<ITypeReference> exceptions) {
+        Set<ITypeReference> exceptionCopy = new HashSet<ITypeReference>(
+                exceptions);
+
+        Iterator<ITypeReference> iterator = exceptionCopy.iterator();
+        while (iterator.hasNext()) {
+            ITypeReference exception = iterator.next();
+            if (isRuntimeExceptionOrErrorSubtype(exception)) {
+                iterator.remove();
+            }
+        }
+        exceptionCopy = removeSpecializations(exceptionCopy);
+        return exceptionCopy;
+    }
+
+    private Set<ITypeReference> removeSpecializations(
+            Set<ITypeReference> exceptions) {
+        Set<ITypeReference> exceptionCopy = new HashSet<ITypeReference>(
+                exceptions);
+        for (ITypeReference type : exceptions) {
+            Iterator<ITypeReference> it = exceptionCopy.iterator();
+            while (it.hasNext()) {
+                ITypeReference subType = it.next();
+                if (isSuperClass(getClassDefinition(type),
+                        getClassDefinition(subType))) {
+                    it.remove();
+                }
+            }
+        }
+        return exceptionCopy;
+    }
+
+    /**
+     * Returns true if superC is a super class of subC.
+     */
+    private boolean isSuperClass(IClassDefinition superC,
+            IClassDefinition subC) {
+        if (superC == null || subC == null) {
+            return false;
+        }
+
+        if (subC.getSuperClass() == null) {
+            return false;
+        } else {
+            if (getClassDefinition(subC.getSuperClass()).equals(superC)) {
+                return true;
+            } else {
+                return isSuperClass(superC, getClassDefinition(subC
+                        .getSuperClass()));
+            }
+        }
+    }
+
+    private boolean isSuperInterface(IClassDefinition superClass,
+            IClassDefinition subClass) {
+        if (superClass == null || subClass == null) {
+            return false;
+        }
+
+        if (subClass.getInterfaces() == null) {
+            return false;
+        } else {
+            if (getClassDefinitions(subClass.getInterfaces()).contains(
+                    superClass)) {
+                return true;
+            } else {
+                for (ITypeReference subType : subClass.getInterfaces()) {
+                    if (isSuperInterface(superClass,
+                            getClassDefinition(subType))) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+        }
+    }
+
+    private Set<IClassDefinition> getClassDefinitions(
+            Set<ITypeReference> references) {
+        Set<IClassDefinition> definitions = new HashSet<IClassDefinition>();
+        for (ITypeReference ref : references) {
+            definitions.add(getClassDefinition(ref));
+        }
+        return definitions;
+    }
+
+    /**
+     * Returns null if type is not one of:
+     * <ul>
+     * <li>IClassReference</li>
+     * <li>IParameterizedType</li>
+     * </ul>
+     */
+    private IClassDefinition getClassDefinition(ITypeReference type) {
+        assert type != null;
+
+        IClassDefinition returnValue = null;
+        if (type instanceof IClassReference) {
+            returnValue = ((IClassReference) type).getClassDefinition();
+        } else if (type instanceof IParameterizedType) {
+            returnValue = ((IParameterizedType) type).getRawType()
+                    .getClassDefinition();
+        }
+        return returnValue;
+    }
+
+    private boolean isRuntimeExceptionOrErrorSubtype(ITypeReference exception) {
+
+        IClassDefinition clazz = getClassDefinition(exception);
+        if (clazz != null) {
+            if (isRuntimeExceptionOrError(clazz)) {
+                return true;
+            } else if (clazz.getSuperClass() != null) {
+                return isRuntimeExceptionOrErrorSubtype(clazz.getSuperClass());
+            } else {
+                return false;
+            }
+        }
+        return false;
+    }
+
+    private boolean isRuntimeExceptionOrError(IClassDefinition exception) {
+        if (exception == null) {
+            return false;
+        }
+        String packageName = exception.getPackageName();
+        String className = exception.getName();
+
+        if (packageName != null && className != null
+                && "java.lang".equals(packageName)) {
+            return "RuntimeException".equals(className)
+                    || "Error".equals(className);
+        }
+        return false;
+    }
+
+    private IConstructorDelta compareConstructor(IConstructor from,
+            IConstructor to) {
+        SigConstructorDelta constructorDelta = null;
+        Set<IModifierDelta> modiferDeltas = compareModifiers(from
+                .getModifiers(), to.getModifiers());
+        if (modiferDeltas != null) {
+            constructorDelta = new SigConstructorDelta(from, to);
+            constructorDelta.setModifierDeltas(modiferDeltas);
+        }
+
+        Set<IParameterDelta> parameterDeltas = compareParameterSequence(from
+                .getParameters(), to.getParameters());
+        if (parameterDeltas != null) {
+            if (constructorDelta == null) {
+                constructorDelta = new SigConstructorDelta(from, to);
+            }
+            constructorDelta.setParameterDeltas(parameterDeltas);
+        }
+
+        Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from
+                .getAnnotations(), to.getAnnotations());
+        if (annotationDeltas != null) {
+            if (constructorDelta == null) {
+                constructorDelta = new SigConstructorDelta(from, to);
+            }
+            constructorDelta.setAnnotationDeltas(annotationDeltas);
+        }
+
+        Set<ITypeVariableDefinitionDelta> typeParameterDeltas =
+                compareTypeVariableSequence(from.getTypeParameters(),
+                        to.getTypeParameters());
+        if (typeParameterDeltas != null) {
+            if (constructorDelta == null) {
+                constructorDelta = new SigConstructorDelta(from, to);
+            }
+            constructorDelta.setTypeVariableDeltas(typeParameterDeltas);
+        }
+
+        Set<ITypeReferenceDelta<?>> exceptionDeltas = compareTypes(
+                normalizeExceptions(from.getExceptions()),
+                normalizeExceptions(to.getExceptions()));
+        if (exceptionDeltas != null) {
+            if (constructorDelta == null) {
+                constructorDelta = new SigConstructorDelta(from, to);
+            }
+            constructorDelta.setExceptionDeltas(exceptionDeltas);
+        }
+        return constructorDelta;
+    }
+
+    private Set<IParameterDelta> compareParameterSequence(
+            List<IParameter> from, List<IParameter> to) {
+        assert from.size() == to.size();
+        Set<IParameterDelta> deltas = new HashSet<IParameterDelta>();
+        Iterator<IParameter> fromIterator = from.iterator();
+        Iterator<IParameter> toIterator = to.iterator();
+        while (fromIterator.hasNext() && toIterator.hasNext()) {
+            IParameterDelta delta = compareParameter(fromIterator.next(),
+                    toIterator.next());
+            if (delta != null) {
+                deltas.add(delta);
+            }
+        }
+        return deltas.isEmpty() ? null : deltas;
+    }
+
+    private IParameterDelta compareParameter(IParameter from, IParameter to) {
+        SigParameterDelta delta = null;
+        ITypeReferenceDelta<?> typeDelta = compareType(from.getType(), to
+                .getType(), false);
+        if (typeDelta != null) {
+            if (delta == null) {
+                delta = new SigParameterDelta(from, to);
+            }
+            delta.setTypeDelta(typeDelta);
+        }
+
+        Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from
+                .getAnnotations(), to.getAnnotations());
+        if (annotationDeltas != null) {
+            if (delta == null) {
+                delta = new SigParameterDelta(from, to);
+            }
+            delta.setAnnotationDeltas(annotationDeltas);
+        }
+        return delta;
+    }
+
+    private Set<ITypeVariableDefinitionDelta> compareTypeVariableSequence(
+            List<ITypeVariableDefinition> from,
+            List<ITypeVariableDefinition> to) {
+        Set<ITypeVariableDefinitionDelta> deltas =
+                new HashSet<ITypeVariableDefinitionDelta>();
+        if (from.size() != to.size()) {
+            for (ITypeVariableDefinition fromVariable : from) {
+                deltas.add(new SigTypeVariableDefinitionDelta(fromVariable,
+                        null));
+            }
+            for (ITypeVariableDefinition toVariable : to) {
+                deltas
+                        .add(new SigTypeVariableDefinitionDelta(null,
+                                toVariable));
+            }
+        }
+
+        Iterator<ITypeVariableDefinition> fromIterator = from.iterator();
+        Iterator<ITypeVariableDefinition> toIterator = to.iterator();
+        while (fromIterator.hasNext() && toIterator.hasNext()) {
+            ITypeVariableDefinitionDelta delta = compareTypeVariableDefinition(
+                    fromIterator.next(), toIterator.next());
+            if (delta != null) {
+                deltas.add(delta);
+            }
+        }
+        return deltas.isEmpty() ? null : deltas;
+    }
+
+    private ITypeVariableDefinitionDelta compareTypeVariableDefinition(
+            ITypeVariableDefinition from, ITypeVariableDefinition to) {
+        IGenericDeclarationDelta declarationDelta = compareGenericDeclaration(
+                from, to);
+
+        if (declarationDelta != null) {
+            SigTypeVariableDefinitionDelta delta =
+                    new SigTypeVariableDefinitionDelta(from, to);
+            delta.setGenericDeclarationDelta(declarationDelta);
+            return delta;
+        }
+        IUpperBoundsDelta upperBoundDelta = compareUpperBounds(from
+                .getUpperBounds(), to.getUpperBounds());
+
+        if (upperBoundDelta != null) {
+            SigTypeVariableDefinitionDelta delta =
+                    new SigTypeVariableDefinitionDelta(from, to);
+            delta.setUpperBoundsDelta(upperBoundDelta);
+            return delta;
+        }
+        return null;
+    }
+
+    private ITypeReferenceDelta<ITypeVariableReference> compareTypeVariableReference(
+            ITypeVariableReference from, ITypeVariableReference to) {
+        IGenericDeclarationDelta declarationDelta = compareGenericDeclaration(
+                from.getTypeVariableDefinition(), to
+                        .getTypeVariableDefinition());
+        if (declarationDelta != null) {
+            SigTypeVariableReferenceDelta delta =
+                    new SigTypeVariableReferenceDelta(from, to);
+            delta.setGenericDeclarationDelta(declarationDelta);
+            return delta;
+        }
+        return null;
+    }
+
+    private Set<IModifierDelta> compareModifiers(Set<Modifier> from,
+            Set<Modifier> to) {
+        return compareSets(from, to,
+                new SigComparator<Modifier, IModifierDelta>() {
+                    public boolean considerEqualElement(Modifier from,
+                            Modifier to) {
+                        return from.equals(to);
+                    }
+
+                    public IModifierDelta createAddRemoveDelta(Modifier from,
+                            Modifier to) {
+                        return new SigModifierDelta(from, to);
+                    }
+
+                    public IModifierDelta createChangedDelta(Modifier from,
+                            Modifier to) {
+                        return null;
+                    }
+                });
+    }
+
+
+    private IFieldDelta compareField(IField from, IField to) {
+        SigFieldDelta fieldDelta = null;
+
+        Set<IModifierDelta> modiferDeltas = compareModifiers(from
+                .getModifiers(), to.getModifiers());
+        if (modiferDeltas != null) {
+            fieldDelta = new SigFieldDelta(from, to);
+            fieldDelta.setModifierDeltas(modiferDeltas);
+        }
+
+        Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from
+                .getAnnotations(), to.getAnnotations());
+        if (annotationDeltas != null) {
+            if (fieldDelta == null) {
+                fieldDelta = new SigFieldDelta(from, to);
+            }
+            fieldDelta.setAnnotationDeltas(annotationDeltas);
+        }
+
+        ITypeReferenceDelta<?> typeDelta = compareType(from.getType(), to
+                .getType(), false);
+        if (typeDelta != null) {
+            if (fieldDelta == null) {
+                fieldDelta = new SigFieldDelta(from, to);
+            }
+            fieldDelta.setTypeDelta(typeDelta);
+        }
+        return fieldDelta;
+    }
+
+    private IEnumConstantDelta compareEnumConstant(IEnumConstant from,
+            IEnumConstant to) {
+        SigEnumConstantDelta enumConstantDelta = null;
+
+        Set<IModifierDelta> modiferDeltas = compareModifiers(from
+                .getModifiers(), to.getModifiers());
+        if (modiferDeltas != null) {
+            enumConstantDelta = new SigEnumConstantDelta(from, to);
+            enumConstantDelta.setModifierDeltas(modiferDeltas);
+        }
+
+        Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from
+                .getAnnotations(), to.getAnnotations());
+        if (annotationDeltas != null) {
+            if (enumConstantDelta == null) {
+                enumConstantDelta = new SigEnumConstantDelta(from, to);
+            }
+            enumConstantDelta.setAnnotationDeltas(annotationDeltas);
+        }
+
+        ITypeReferenceDelta<?> typeDelta = compareType(from.getType(), to
+                .getType(), false);
+        if (typeDelta != null) {
+            if (enumConstantDelta == null) {
+                enumConstantDelta = new SigEnumConstantDelta(from, to);
+            }
+            enumConstantDelta.setTypeDelta(typeDelta);
+        }
+
+        // FIXME ordinal not supported in dex
+        // ValueDelta ordinalDelta = compareValue(from.getOrdinal(),
+        // to.getOrdinal());
+        // if (ordinalDelta != null) {
+        // if (enumConstantDelta == null) {
+        // enumConstantDelta = new SigEnumConstantDelta(from, to);
+        // }
+        // enumConstantDelta.setOrdinalDelta(ordinalDelta);
+        // }
+
+        return enumConstantDelta;
+    }
+
+    private IAnnotationFieldDelta compareAnnotationField(IAnnotationField from,
+            IAnnotationField to) {
+        SigAnnotationFieldDelta annotationFieldDelta = null;
+
+        Set<IModifierDelta> modiferDeltas = compareModifiers(from
+                .getModifiers(), to.getModifiers());
+        if (modiferDeltas != null) {
+            annotationFieldDelta = new SigAnnotationFieldDelta(from, to);
+            annotationFieldDelta.setModifierDeltas(modiferDeltas);
+        }
+
+        Set<IAnnotationDelta> annotationDeltas = compareAnnotations(from
+                .getAnnotations(), to.getAnnotations());
+        if (annotationDeltas != null) {
+            if (annotationFieldDelta == null) {
+                annotationFieldDelta = new SigAnnotationFieldDelta(from, to);
+            }
+            annotationFieldDelta.setAnnotationDeltas(annotationDeltas);
+        }
+
+        ITypeReferenceDelta<?> typeDelta = compareType(from.getType(), to
+                .getType(), false);
+        if (typeDelta != null) {
+            if (annotationFieldDelta == null) {
+                annotationFieldDelta = new SigAnnotationFieldDelta(from, to);
+            }
+            annotationFieldDelta.setTypeDelta(typeDelta);
+        }
+
+        IValueDelta defaultValueDelta = compareValue(from.getDefaultValue(), to
+                .getDefaultValue());
+        if (defaultValueDelta != null) {
+            if (annotationFieldDelta == null) {
+                annotationFieldDelta = new SigAnnotationFieldDelta(from, to);
+            }
+            annotationFieldDelta.setDefaultValueDelta(defaultValueDelta);
+        }
+
+        return annotationFieldDelta;
+    }
+
+    private SigValueDelta compareValue(Object from, Object to) {
+        // same value
+        if (from == null && to == null) {
+            return null;
+        }
+
+        // one of both is null and other is not
+        if (from == null || to == null) {
+            return new SigValueDelta(from, to);
+        }
+
+        SigValueDelta delta = null;
+        // different types
+        if (from.getClass() == to.getClass()) {
+            if (from.getClass().isArray()) {
+                Object[] fromArray = (Object[]) from;
+                Object[] toArray = (Object[]) from;
+                if (!Arrays.equals(fromArray, toArray)) {
+                    delta = new SigValueDelta(from, to);
+                }
+            } else if (from instanceof IEnumConstant) {
+                IEnumConstantDelta enumConstantDelta = compareEnumConstant(
+                        (IEnumConstant) from, (IEnumConstant) to);
+                if (enumConstantDelta != null) {
+                    delta = new SigValueDelta(from, to);
+                }
+            } else if (from instanceof IAnnotation) {
+                IAnnotationDelta annotationDelta = compareAnnotation(
+                        (IAnnotation) from, (IAnnotation) to);
+                if (annotationDelta != null) {
+                    delta = new SigValueDelta(from, to);
+                }
+            } else if (from instanceof IField) {
+                IFieldDelta fieldDelta = compareField((IField) from,
+                        (IField) to);
+                if (fieldDelta != null) {
+                    delta = new SigValueDelta(from, to);
+                }
+            } else if (from instanceof ITypeReference) {
+                ITypeReferenceDelta<? extends ITypeReference> typeDelta =
+                        compareType((ITypeReference) from, (ITypeReference) to,
+                                false);
+                if (typeDelta != null) {
+                    delta = new SigValueDelta(from, to);
+                }
+            } else if (!from.equals(to)) {
+                delta = new SigValueDelta(from, to);
+            }
+
+        } else if (!(from == null && to == null)) {
+            delta = new SigValueDelta(from, to);
+        }
+        return delta;
+    }
+
+    private boolean considerEqualTypes(ITypeReference from, ITypeReference to) {
+        assert from != null && to != null;
+
+        if (implementInterface(from, to, IPrimitiveType.class)) {
+            return comparePrimitiveType((IPrimitiveType) from,
+                    (IPrimitiveType) to) == null;
+        }
+        if (implementInterface(from, to, IClassReference.class)) {
+            return sameClassDefinition(((IClassReference) from)
+                    .getClassDefinition(), ((IClassReference) to)
+                    .getClassDefinition());
+        }
+        if (implementInterface(from, to, IArrayType.class)) {
+            return considerEqualTypes(((IArrayType) from).getComponentType(),
+                    ((IArrayType) to).getComponentType());
+        }
+        if (implementInterface(from, to, IParameterizedType.class)) {
+            return compareClassReference(((IParameterizedType) from)
+                    .getRawType(), ((IParameterizedType) to)
+                    .getRawType()) == null;
+        }
+        if (implementInterface(from, to, ITypeVariableReference.class)) {
+            return compareTypeVariableReference((ITypeVariableReference) from,
+                    (ITypeVariableReference) to) == null;
+        }
+
+        return false;
+    }
+
+    private Set<ITypeReference> fromComparison = new HashSet<ITypeReference>();
+    private Set<ITypeReference> toComparison = new HashSet<ITypeReference>();
+
+
+    private boolean areInComparison(ITypeReference from, ITypeReference to) {
+        return fromComparison.contains(from) && toComparison.contains(to);
+    }
+
+    private void markInComparison(ITypeReference from, ITypeReference to) {
+        fromComparison.add(from);
+        toComparison.add(to);
+    }
+
+    private void markFinishedComparison(ITypeReference from,
+            ITypeReference to) {
+        fromComparison.remove(from);
+        toComparison.remove(to);
+    }
+
+    private ITypeReferenceDelta<? extends ITypeReference> compareType(
+            ITypeReference from, ITypeReference to, boolean acceptErasedTypes) {
+
+        if (from == null && to == null) {
+            return null;
+        }
+        if ((from == null && to != null) || (from != null && to == null)) {
+            return new SigTypeDelta<ITypeReference>(from, to);
+        }
+        if (areInComparison(from, to)) {
+            return null;
+        }
+        try {
+            markInComparison(from, to);
+
+            if (implementInterface(from, to, IPrimitiveType.class)) {
+                return comparePrimitiveType((IPrimitiveType) from,
+                        (IPrimitiveType) to);
+            }
+            if (implementInterface(from, to, IClassReference.class)) {
+                return compareClassReference((IClassReference) from,
+                        (IClassReference) to);
+            }
+            if (implementInterface(from, to, IArrayType.class)) {
+                return compareArrayType((IArrayType) from, (IArrayType) to);
+            }
+            if (implementInterface(from, to, IParameterizedType.class)) {
+                return compareParameterizedType((IParameterizedType) from,
+                        (IParameterizedType) to, acceptErasedTypes);
+            }
+            if (implementInterface(from, to, ITypeVariableReference.class)) {
+                return compareTypeVariableReference(
+                        (ITypeVariableReference) from,
+                        (ITypeVariableReference) to);
+            }
+            if (implementInterface(from, to, IWildcardType.class)) {
+                return compareWildcardType((IWildcardType) from,
+                        (IWildcardType) to);
+            }
+
+            if (acceptErasedTypes) {
+                if (isGeneric(from) && !isGeneric(to)) {
+                    return compareType(getErasedType(from), to, false);
+                }
+
+                if (!isGeneric(from) && isGeneric(to)) {
+                    return compareType(from, getErasedType(to), false);
+                }
+            }
+            return new SigTypeDelta<ITypeReference>(from, to);
+        } finally {
+            markFinishedComparison(from, to);
+        }
+    }
+
+    private boolean isGeneric(ITypeReference reference) {
+        if (reference instanceof IParameterizedType
+                || reference instanceof ITypeVariableReference
+                || reference instanceof IWildcardType) {
+            return true;
+        }
+        if (reference instanceof IArrayType) {
+            return isGeneric(((IArrayType) reference).getComponentType());
+        }
+        return false;
+    }
+
+    private ITypeReference getErasedType(ITypeReference reference) {
+
+        if (reference instanceof IParameterizedType) {
+            return ((IParameterizedType) reference).getRawType();
+        }
+        if (reference instanceof ITypeVariableReference) {
+            ITypeVariableDefinition typeVariableDefinition =
+                    ((ITypeVariableReference) reference)
+                            .getTypeVariableDefinition();
+            return getErasedType(
+                    typeVariableDefinition.getUpperBounds().get(0));
+        }
+        if (reference instanceof IWildcardType) {
+            return getErasedType(((IWildcardType) reference).getUpperBounds()
+                    .get(0));
+        }
+        if (reference instanceof IArrayType) {
+            // FIXME implement with erasure projection?
+            return new SigArrayType(getErasedType(((IArrayType) reference)
+                    .getComponentType()));
+        }
+        if (reference instanceof IPrimitiveType) {
+            return reference;
+        }
+        if (reference instanceof IClassReference) {
+            return reference;
+        }
+        throw new IllegalArgumentException("Unexpected type: " + reference);
+    }
+
+    private boolean implementInterface(ITypeReference from, ITypeReference to,
+            Class<?> check) {
+        return check.isAssignableFrom(from.getClass())
+                && check.isAssignableFrom(to.getClass());
+    }
+
+    private IWildcardTypeDelta compareWildcardType(IWildcardType from,
+            IWildcardType to) {
+        SigWildcardTypeDelta delta = null;
+
+        ITypeReference fromLowerBound = from.getLowerBound();
+        ITypeReference toLowerBound = to.getLowerBound();
+
+        ITypeReferenceDelta<?> lowerBoundDelta = compareType(fromLowerBound,
+                toLowerBound, false);
+        if (lowerBoundDelta != null) {
+            delta = new SigWildcardTypeDelta(from, to);
+            delta.setLowerBoundDelta(lowerBoundDelta);
+        }
+
+        IUpperBoundsDelta upperBoundsDelta = compareUpperBounds(from
+                .getUpperBounds(), to.getUpperBounds());
+        if (upperBoundsDelta != null) {
+            if (delta == null) {
+                delta = new SigWildcardTypeDelta(from, to);
+            }
+            delta.setUpperBoundDelta(upperBoundsDelta);
+        }
+        return delta;
+    }
+
+    private IGenericDeclarationDelta compareGenericDeclaration(
+            ITypeVariableDefinition fromVariable,
+            ITypeVariableDefinition toVariable) {
+        IGenericDeclarationDelta delta = null;
+
+        IGenericDeclaration from = fromVariable.getGenericDeclaration();
+        IGenericDeclaration to = toVariable.getGenericDeclaration();
+
+        if (from != null && to != null) {
+
+            if (from.getClass() != to.getClass()) {
+                delta = new SigGenericDeclarationDelta(from, to);
+            } else if (from instanceof IClassDefinition) {
+                IClassDefinition fromDeclaringClass = (IClassDefinition) from;
+                IClassDefinition toDeclaringClass = (IClassDefinition) to;
+
+                if (!sameClassDefinition(fromDeclaringClass,
+                        toDeclaringClass)) {
+                    delta = new SigGenericDeclarationDelta(from, to);
+                }
+
+            } else if (from instanceof IConstructor) {
+                IConstructor fromConstructor = (IConstructor) from;
+                IConstructor toConstructor = (IConstructor) from;
+
+                String fromConstructorName = fromConstructor.getName();
+                String fromClassName = fromConstructor.getDeclaringClass()
+                        .getQualifiedName();
+
+                String toConstructorName = toConstructor.getName();
+                String toClassName = toConstructor.getDeclaringClass()
+                        .getQualifiedName();
+
+                if ((!fromConstructorName.equals(toConstructorName))
+                        || (!fromClassName.equals(toClassName))) {
+                    delta = new SigGenericDeclarationDelta(from, to);
+                }
+
+            } else if (from instanceof IMethod) {
+                IMethod fromMethod = (IMethod) from;
+                IMethod toMethod = (IMethod) from;
+
+                String fromConstructorName = fromMethod.getName();
+                String fromClassName = fromMethod.getDeclaringClass()
+                        .getQualifiedName();
+
+                String toConstructorName = toMethod.getName();
+                String toClassName = toMethod.getDeclaringClass()
+                        .getQualifiedName();
+
+                if ((!fromConstructorName.equals(toConstructorName))
+                        || (!fromClassName.equals(toClassName))) {
+                    delta = new SigGenericDeclarationDelta(from, to);
+                }
+            } else {
+                throw new IllegalStateException("Invlaid eclaration site: "
+                        + from);
+            }
+
+            // check position
+            int fromPosition = getPositionOf(fromVariable, from);
+            int toPosition = getPositionOf(toVariable, to);
+
+            if (fromPosition != toPosition) {
+                delta = new SigGenericDeclarationDelta(from, to);
+            }
+
+
+        } else {
+            // one of both is null
+            delta = new SigGenericDeclarationDelta(from, to);
+        }
+        return delta;
+    }
+
+    private int getPositionOf(ITypeVariableDefinition variable,
+            IGenericDeclaration declaration) {
+        return declaration.getTypeParameters().indexOf(variable);
+    }
+
+    private IUpperBoundsDelta compareUpperBounds(List<ITypeReference> from,
+            List<ITypeReference> to) {
+        if (from.isEmpty() && to.isEmpty()) {
+            return null;
+        }
+        SigUpperBoundsDelta delta = null;
+
+        ITypeReference fromFirstUpperBound = from.get(0);
+        ITypeReference toFirstUpperBound = to.get(0);
+
+        ITypeReferenceDelta<?> firstUpperBoundDelta = compareType(
+                fromFirstUpperBound, toFirstUpperBound, false);
+        if (firstUpperBoundDelta != null) {
+            delta = new SigUpperBoundsDelta(from, to);
+            delta.setFirstUpperBoundDelta(firstUpperBoundDelta);
+        } else {
+            // normalize
+            Set<ITypeReference> normalizedfrom = removeGeneralizations(
+                    new HashSet<ITypeReference>(from));
+            Set<ITypeReference> normalizedto = removeGeneralizations(
+                    new HashSet<ITypeReference>(to));
+
+            Set<ITypeReferenceDelta<?>> remainingUpperBoundsDelta =
+                    compareTypes(normalizedfrom, normalizedto);
+            if (remainingUpperBoundsDelta != null) {
+                delta = new SigUpperBoundsDelta(from, to);
+                delta.setRemainingUpperBoundDeltas(remainingUpperBoundsDelta);
+            }
+        }
+        return delta;
+    }
+
+    private Set<ITypeReference> removeGeneralizations(
+            Set<ITypeReference> bounds) {
+        Set<ITypeReference> boundsCopy = new HashSet<ITypeReference>(bounds);
+        for (ITypeReference type : bounds) {
+            Iterator<ITypeReference> it = boundsCopy.iterator();
+            while (it.hasNext()) {
+                ITypeReference superType = it.next();
+                if (isSuperClass(getClassDefinition(superType),
+                        getClassDefinition(type))
+                        || isSuperInterface(getClassDefinition(superType),
+                                getClassDefinition(type))) {
+                    it.remove();
+                }
+            }
+        }
+        return boundsCopy;
+    }
+
+    private IParameterizedTypeDelta compareParameterizedType(
+            IParameterizedType from, IParameterizedType to,
+            boolean ignoreTypeArguments) {
+
+        SigParameterizedTypeDelta delta = null;
+        // check raw type
+        ITypeReferenceDelta<?> rawTypeDelta = compareType(from.getRawType(), to
+                .getRawType(), false);
+        if (rawTypeDelta != null) {
+            delta = new SigParameterizedTypeDelta(from, to);
+            delta.setRawTypeDelta(rawTypeDelta);
+        } else {
+            // check owner type
+            ITypeReferenceDelta<?> ownerTypeDelta = compareType(from
+                    .getOwnerType(), to.getOwnerType(), false);
+            if (ownerTypeDelta != null) {
+                delta = new SigParameterizedTypeDelta(from, to);
+                delta.setOwnerTypeDelta(ownerTypeDelta);
+            } else {
+                // check argument type
+                if (!ignoreTypeArguments) {
+                    Set<ITypeReferenceDelta<?>> argumentTypeDeltas =
+                            compareTypeSequence(from.getTypeArguments(),
+                                    to.getTypeArguments(), false);
+                    if (argumentTypeDeltas != null) {
+                        delta = new SigParameterizedTypeDelta(from, to);
+                        delta.setArgumentTypeDeltas(argumentTypeDeltas);
+                    }
+                }
+            }
+        }
+        return delta;
+    }
+
+    private Set<ITypeReferenceDelta<? extends ITypeReference>> compareTypeSequence(
+            List<ITypeReference> from, List<ITypeReference> to,
+            boolean ignoreTypeArguments) {
+        Set<ITypeReferenceDelta<?>> deltas =
+                new HashSet<ITypeReferenceDelta<?>>();
+        if (from.size() != to.size()) {
+
+            for (ITypeReference type : from) {
+                deltas.add(new SigTypeDelta<ITypeReference>(type, null));
+            }
+            for (ITypeReference type : to) {
+                deltas.add(new SigTypeDelta<ITypeReference>(null, type));
+            }
+            return deltas;
+        }
+
+        Iterator<? extends ITypeReference> fromIterator = from.iterator();
+        Iterator<? extends ITypeReference> toIterator = to.iterator();
+        while (fromIterator.hasNext() && toIterator.hasNext()) {
+            ITypeReferenceDelta<?> delta = compareType(fromIterator.next(),
+                    toIterator.next(), ignoreTypeArguments);
+            if (delta != null) {
+                deltas.add(delta);
+            }
+        }
+        return deltas.isEmpty() ? null : deltas;
+    }
+
+    private Set<ITypeReferenceDelta<? extends ITypeReference>> compareTypes(
+            Set<ITypeReference> from, Set<ITypeReference> to) {
+        return compareSets(from, to,
+                new SigComparator<ITypeReference, ITypeReferenceDelta<? extends ITypeReference>>() {
+                    public ITypeReferenceDelta<? extends ITypeReference> createAddRemoveDelta(
+                            ITypeReference from, ITypeReference to) {
+                        return new SigTypeDelta<ITypeReference>(from, to);
+                    }
+
+                    public boolean considerEqualElement(ITypeReference from,
+                            ITypeReference to) {
+                        return considerEqualTypes(from, to);
+                    }
+
+                    public ITypeReferenceDelta<? extends ITypeReference> createChangedDelta(
+                            ITypeReference from, ITypeReference to) {
+                        return compareType(from, to, false);
+                    }
+                });
+    }
+
+    private static interface SigComparator<T, S extends IDelta<? extends T>> {
+        boolean considerEqualElement(T from, T to);
+
+        S createChangedDelta(T from, T to);
+
+        /**
+         * If null is returned, it will be ignored.
+         */
+        S createAddRemoveDelta(T from, T to);
+    }
+
+
+    private <T, S extends IDelta<? extends T>> Set<S> compareSets(Set<T> from,
+            Set<T> to, SigComparator<T, S> comparator) {
+
+        Set<T> toCopy = new HashSet<T>(to);
+        Set<S> deltas = new HashSet<S>();
+
+        for (T fromType : from) {
+            Iterator<T> toIterator = toCopy.iterator();
+            boolean equals = false;
+            boolean hasNext = toIterator.hasNext();
+
+            while (hasNext && !equals) {
+                T toElement = toIterator.next();
+                equals = comparator.considerEqualElement(fromType, toElement);
+                if (equals) {
+                    S compare = comparator.createChangedDelta(fromType,
+                            toElement);
+                    if (compare != null) {
+                        deltas.add(compare);
+                    }
+                }
+                hasNext = toIterator.hasNext();
+            }
+
+            if (equals) {
+                toIterator.remove();
+            } else {
+                S delta = comparator.createAddRemoveDelta(fromType, null);
+                if (delta != null) {
+                    deltas.add(delta);
+                }
+            }
+        }
+
+        for (T type : toCopy) {
+            S delta = comparator.createAddRemoveDelta(null, type);
+            if (delta != null) {
+                deltas.add(delta);
+            }
+        }
+        return deltas.isEmpty() ? null : deltas;
+    }
+
+
+    private ITypeReferenceDelta<?> compareArrayType(IArrayType from,
+            IArrayType to) {
+        ITypeReferenceDelta<?> componentTypeDelta = compareType(from
+                .getComponentType(), to.getComponentType(), false);
+        if (componentTypeDelta != null) {
+            SigArrayTypeDelta delta = new SigArrayTypeDelta(from, to);
+            delta.setComponentTypeDelta(componentTypeDelta);
+            return delta;
+        }
+        return null;
+    }
+
+    private ITypeReferenceDelta<IClassReference> compareClassReference(
+            IClassReference fromRef, IClassReference toRef) {
+        IClassDefinition from = fromRef.getClassDefinition();
+        IClassDefinition to = toRef.getClassDefinition();
+
+        if (!sameClassDefinition(from, to)) {
+            return new SigClassReferenceDelta(fromRef, toRef);
+        }
+        return null;
+    }
+
+
+    private boolean sameClassDefinition(IClassDefinition from,
+            IClassDefinition to) {
+        boolean sameName = from.getName().equals(to.getName());
+        boolean samePackage = from.getPackageName().equals(to.getPackageName());
+
+        Kind fromKind = from.getKind();
+        Kind toKind = to.getKind();
+        boolean sameKind = (fromKind == null || toKind == null)
+                || fromKind.equals(toKind);
+
+        return sameName && samePackage && sameKind;
+    }
+
+    private IPrimitiveTypeDelta comparePrimitiveType(IPrimitiveType from,
+            IPrimitiveType to) {
+        if (!from.equals(to)) {
+            return new SigPrimitiveTypeDelta(from, to);
+        }
+        return null;
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/IApiComparator.java b/tools/signature-tools/src/signature/compare/IApiComparator.java
new file mode 100644
index 0000000..08ed97f
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/IApiComparator.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare;
+
+import signature.compare.model.IApiDelta;
+import signature.model.IApi;
+
+/**
+ * {@code IApiComparator} defines the functionality of a signature comparator.
+ */
+public interface IApiComparator {
+
+    /**
+     * Returns a difference model which describes the differences from {@code
+     * fromApi} to {@code toApi}.
+     * 
+     * @param fromApi
+     *            differences are computed relative to {@code fromApi}
+     * @param toApi
+     *            the target signature model
+     * @return a difference model which describes the differences from {@code
+     *         fromApi} to {@code toApi}
+     */
+    IApiDelta compare(IApi fromApi, IApi toApi);
+}
diff --git a/tools/signature-tools/src/signature/compare/Main.java b/tools/signature-tools/src/signature/compare/Main.java
new file mode 100644
index 0000000..80edb45
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/Main.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare;
+
+import signature.UsageException;
+import signature.compare.model.IApiDelta;
+import signature.compare.model.IPackageDelta;
+import signature.compare.model.impl.SigDelta;
+import signature.converter.Visibility;
+import signature.converter.dex.DexFactory;
+import signature.converter.doclet.DocletFactory;
+import signature.io.IApiDeltaExternalizer;
+import signature.io.IApiLoader;
+import signature.io.html.HtmlDeltaExternalizer;
+import signature.io.impl.BinaryApi;
+import signature.model.IApi;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Driver class for the --compare option.
+ */
+public class Main {
+
+    /**
+     * <pre>
+     * --from=(doclet | dex | sig) <sourcefiles>
+     * --name <name>
+     * --to=(doclet | dex | sig) <sourcefiles>
+     * --name <name>
+     * --out directory
+     * --packages packageName{ packageName}
+     * </pre>
+     */
+    public static void main(String[] args) throws IOException {
+        int at = 0;
+
+        if (!"--from".equals(args[at])) {
+            throw new UsageException();
+        }
+        String fromType = args[++at];
+
+        boolean hasName = false;
+        Set<String> fromFiles = new HashSet<String>();
+        ++at;
+        for (/* at */; at < args.length; at++) {
+            if ("--name".equals(args[at])) {
+                hasName = true;
+                break;
+            }
+            if ("--to".equals(args[at])) {
+                break;
+            }
+            fromFiles.add(args[at]);
+        }
+
+        String nameFrom = null;
+        if (hasName) {
+            nameFrom = "";
+            if (!"--name".equals(args[at])) {
+                throw new UsageException();
+            }
+            ++at;
+            for (/* at */; at < args.length; at++) {
+                if ("--to".equals(args[at])) {
+                    break;
+                }
+                nameFrom += args[at];
+                nameFrom += " ";
+            }
+            nameFrom = nameFrom.trim();
+        }
+
+        if (!"--to".equals(args[at])) {
+            throw new UsageException();
+        }
+        String toType = args[++at];
+
+        hasName = false;
+        Set<String> toFiles = new HashSet<String>();
+        ++at;
+        for (/* at */; at < args.length; at++) {
+            if ("--name".equals(args[at])) {
+                hasName = true;
+                break;
+            }
+            if ("--out".equals(args[at])) {
+                break;
+            }
+            toFiles.add(args[at]);
+        }
+
+        String nameTo = null;
+        if (hasName) {
+            nameTo = "";
+            if (!"--name".equals(args[at])) {
+                throw new UsageException();
+            }
+            ++at;
+            for (/* at */; at < args.length; at++) {
+                if ("--out".equals(args[at])) {
+                    break;
+                }
+                nameTo += args[at];
+                nameTo += " ";
+            }
+            nameTo = nameTo.trim();
+        }
+
+        if (!"--out".equals(args[at])) {
+            throw new UsageException();
+        }
+        String output = args[++at];
+
+        if (!"--packages".equals(args[++at])) {
+            throw new UsageException();
+        }
+        Set<String> packages = new HashSet<String>();
+        ++at;
+        for (/* at */; at < args.length; at++) {
+            packages.add(args[at]);
+        }
+
+        IApiComparator comparator = new ApiComparator();
+        IApi fromApi = getApi(fromType, nameFrom, fromFiles, packages);
+        IApi toApi = getApi(toType, nameTo, toFiles, packages);
+
+        IApiDeltaExternalizer externalizer = new HtmlDeltaExternalizer();
+        System.out.println("Writing delta report to " + output);
+        IApiDelta delta = comparator.compare(fromApi, toApi);
+        if (delta == null) {
+            delta = new EmptyDelta(fromApi, toApi);
+        }
+
+        externalizer.externalize(output, delta);
+    }
+
+    private static class EmptyDelta extends SigDelta<IApi> implements
+            IApiDelta {
+        public EmptyDelta(IApi from, IApi to) {
+            super(from, to);
+        }
+
+        public Set<IPackageDelta> getPackageDeltas() {
+            return Collections.emptySet();
+        }
+    }
+
+    private static IApi getApi(String specType, String name,
+            Set<String> fileNames, Set<String> packageNames) throws
+            IOException {
+        System.out.println("Loading " + name + " of type " + specType
+                + " from " + fileNames);
+        IApiLoader factory = null;
+        if ("doclet".equals(specType)) {
+            checkName(name);
+            factory = new DocletFactory();
+        } else if ("dex".equals(specType)) {
+            checkName(name);
+            factory = new DexFactory();
+        } else if ("sig".equals(specType)) {
+            factory = new BinaryApi();
+        } else {
+            throw new UsageException();
+        }
+        return factory.loadApi(name, Visibility.PROTECTED, fileNames,
+                packageNames);
+    }
+
+    private static void checkName(String name) {
+        if (name == null) {
+            throw new UsageException();
+        }
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/DeltaType.java b/tools/signature-tools/src/signature/compare/model/DeltaType.java
new file mode 100644
index 0000000..a3aad2c
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/DeltaType.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+/**
+ * {@code DeltaType} defines the three possible types of a delta.
+ */
+public enum DeltaType {
+    /**
+     * States that an element was added to the toApi.
+     */
+    ADDED,
+    /**
+     * States that an element was removed from the toApi.
+     */
+    REMOVED,
+    /**
+     * States that an element changed.
+     */
+    CHANGED
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IAnnotatableElementDelta.java b/tools/signature-tools/src/signature/compare/model/IAnnotatableElementDelta.java
new file mode 100644
index 0000000..dd41c60
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IAnnotatableElementDelta.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import java.util.Set;
+
+/**
+ * {@code IAnnotatableElementDelta} is the common base interface for deltas
+ * which may have {@link IAnnotationDelta}s.
+ */
+public interface IAnnotatableElementDelta {
+
+    /**
+     * Returns a set of annotation deltas or {@code null} if no deltas are
+     * available.
+     * 
+     * @return a set of annotation deltas, maybe {@code null}
+     */
+    Set<IAnnotationDelta> getAnnotationDeltas();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IAnnotationDelta.java b/tools/signature-tools/src/signature/compare/model/IAnnotationDelta.java
new file mode 100644
index 0000000..2e29358
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IAnnotationDelta.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import java.util.Set;
+
+import signature.model.IAnnotation;
+
+/**
+ * {@code IAnnotationDelta} models the delta between two {@link IAnnotation}
+ * instances.
+ */
+public interface IAnnotationDelta extends IDelta<IAnnotation> {
+
+    /**
+     * Returns a set of annotation element deltas or {@code null} if no deltas
+     * are available.
+     * 
+     * @return a set of annotation element deltas, maybe {@code null}
+     */
+    Set<IAnnotationElementDelta> getAnnotationElementDeltas();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IAnnotationElementDelta.java b/tools/signature-tools/src/signature/compare/model/IAnnotationElementDelta.java
new file mode 100644
index 0000000..4355fdb
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IAnnotationElementDelta.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import signature.model.IAnnotationElement;
+
+/**
+ * {@code IAnnotationElementDelta} models the delta between two
+ * {@link IAnnotationElement} instances.
+ */
+public interface IAnnotationElementDelta extends IDelta<IAnnotationElement> {
+
+    /**
+     * Returns a value delta or {@code null} if no delta is available.
+     * 
+     * @return a value delta, maybe {@code null}
+     */
+    IValueDelta getValueDelta();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IAnnotationFieldDelta.java b/tools/signature-tools/src/signature/compare/model/IAnnotationFieldDelta.java
new file mode 100644
index 0000000..223072a
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IAnnotationFieldDelta.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import signature.model.IAnnotationField;
+
+/**
+ * {@code IAnnotationFieldDelta} models the delta between two
+ * {@link IAnnotationField} instances.
+ */
+public interface IAnnotationFieldDelta extends IMemberDelta<IAnnotationField> {
+
+    /**
+     * Returns the default value delta or {@code null} if no delta is available.
+     * 
+     * @return the default value delta, maybe {@code null}
+     */
+    IValueDelta getDefaultValueDelta();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IApiDelta.java b/tools/signature-tools/src/signature/compare/model/IApiDelta.java
new file mode 100644
index 0000000..78a8c34
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IApiDelta.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import java.util.Set;
+
+import signature.model.IApi;
+
+/**
+ * {@code IApiDelta} models the delta between two {@link IApi} instances.
+ */
+public interface IApiDelta extends IDelta<IApi> {
+
+    /**
+     * Returns a set of package deltas or {@code null} if no deltas are
+     * available.
+     * 
+     * @return a set of package deltas, maybe {@code null}
+     */
+    Set<IPackageDelta> getPackageDeltas();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IArrayTypeDelta.java b/tools/signature-tools/src/signature/compare/model/IArrayTypeDelta.java
new file mode 100644
index 0000000..bb29bcd
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IArrayTypeDelta.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import signature.model.IArrayType;
+
+/**
+ * {@code IArrayTypeDelta} models the delta between two {@link IArrayType}
+ * instances.
+ */
+public interface IArrayTypeDelta extends ITypeReferenceDelta<IArrayType> {
+
+    /**
+     * Returns a component type delta or {@code null} if no delta is available.
+     * 
+     * @return a component type delta, maybe {@code null}
+     */
+    ITypeReferenceDelta<?> getComponentTypeDelta();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IClassDefinitionDelta.java b/tools/signature-tools/src/signature/compare/model/IClassDefinitionDelta.java
new file mode 100644
index 0000000..5cbaf9b
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IClassDefinitionDelta.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import java.util.Set;
+
+import signature.model.IClassDefinition;
+
+/**
+ * {@code IClassDefinitionDelta} models the delta between two
+ * {@link IClassDefinition} instances.
+ */
+public interface IClassDefinitionDelta extends
+        ITypeDefinitionDelta<IClassDefinition>, IAnnotatableElementDelta,
+        ITypeVariableDeltas {
+
+    /**
+     * Returns a set of field deltas or {@code null} if no deltas are available.
+     * 
+     * @return a set of field deltas, maybe {@code null}
+     */
+    Set<IFieldDelta> getFieldDeltas();
+
+    /**
+     * Returns a set of enum constant deltas or {@code null} if no deltas are
+     * available.
+     * 
+     * @return a set of enum constant deltas, maybe {@code null}
+     */
+    Set<IEnumConstantDelta> getEnumConstantDeltas();
+
+    /**
+     * Returns a set of annotation field deltas or {@code null} if no deltas are
+     * available.
+     * 
+     * @return a set of annotation field deltas, maybe {@code null}
+     */
+    Set<IAnnotationFieldDelta> getAnnotationFieldDeltas();
+
+    /**
+     * Returns a set of method deltas or {@code null} if no deltas are
+     * available.
+     * 
+     * @return a set of method deltas, maybe {@code null}
+     */
+    Set<IMethodDelta> getMethodDeltas();
+
+    /**
+     * Returns a set of constructor deltas or {@code null} if no deltas are
+     * available.
+     * 
+     * @return a set of constructor deltas, maybe {@code null}
+     */
+    Set<IConstructorDelta> getConstructorDeltas();
+
+    /**
+     * Returns a set of modifier deltas or {@code null} if no deltas are
+     * available.
+     * 
+     * @return a set of modifier deltas, maybe {@code null}
+     */
+    Set<IModifierDelta> getModifierDeltas();
+
+    /**
+     * Returns a super class delta or {@code null} if no delta is available.
+     * 
+     * @return a super class delta, maybe {@code null}
+     */
+    ITypeReferenceDelta<?> getSuperClassDelta();
+
+    /**
+     * Returns a set of interface deltas or {@code null} if no deltas are
+     * available.
+     * 
+     * @return a set of interface deltas, maybe {@code null}
+     */
+    Set<ITypeReferenceDelta<?>> getInterfaceDeltas();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IConstructorDelta.java b/tools/signature-tools/src/signature/compare/model/IConstructorDelta.java
new file mode 100644
index 0000000..64ba993
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IConstructorDelta.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import signature.model.IConstructor;
+
+/**
+ * {@code IConstructorDelta} models the delta between two {@link IConstructor}
+ * instances.
+ */
+public interface IConstructorDelta extends
+        IExecutableMemberDelta<IConstructor> {
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IDelta.java b/tools/signature-tools/src/signature/compare/model/IDelta.java
new file mode 100644
index 0000000..bd94388
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IDelta.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+/**
+ * {@code IDelta} is the common base interface for all delta model elements. It
+ * describes a delta from a "from" element to a "to" element.
+ * 
+ * @param <T>
+ *            the type of the compared elements
+ */
+public interface IDelta<T> {
+
+    /**
+     * Returns the type of this delta.
+     * 
+     * @return the type of this delta
+     */
+    DeltaType getType();
+
+    /**
+     * Returns the "from" element. Is null if type is {@link DeltaType#ADDED}
+     * 
+     * @return the "from" element
+     */
+    T getFrom();
+
+    /**
+     * Returns the "to" element. Is null if type is {@link DeltaType#REMOVED}
+     * 
+     * @return the "to" element
+     */
+    T getTo();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IEnumConstantDelta.java b/tools/signature-tools/src/signature/compare/model/IEnumConstantDelta.java
new file mode 100644
index 0000000..6590c5a
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IEnumConstantDelta.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import signature.model.IEnumConstant;
+
+/**
+ * {@code IEnumConstantDelta} models the delta between two {@link IEnumConstant}
+ * instances.
+ */
+public interface IEnumConstantDelta extends IMemberDelta<IEnumConstant> {
+    IValueDelta getOrdinalDelta();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IExecutableMemberDelta.java b/tools/signature-tools/src/signature/compare/model/IExecutableMemberDelta.java
new file mode 100644
index 0000000..30f7038
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IExecutableMemberDelta.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import java.util.Set;
+
+import signature.model.IExecutableMember;
+
+/**
+ * {@code IExecutableMemberDelta} models the delta between two
+ * {@link IExecutableMember} instances.
+ */
+public interface IExecutableMemberDelta<T extends IExecutableMember> extends
+        IDelta<T>, ITypeVariableDeltas, IAnnotatableElementDelta {
+
+    /**
+     * Returns a set of modifier deltas or {@code null} if no deltas are
+     * available.
+     * 
+     * @return a set of modifier deltas, maybe {@code null}
+     */
+    Set<IModifierDelta> getModifierDeltas();
+
+    /**
+     * Returns a set of exception deltas or {@code null} if no deltas are
+     * available.
+     * 
+     * @return a set of exception deltas, maybe {@code null}
+     */
+    Set<ITypeReferenceDelta<?>> getExceptionDeltas();
+
+    /**
+     * Returns a set of parameter deltas or {@code null} if no deltas are
+     * available.
+     * 
+     * @return a set of parameter deltas, maybe {@code null}
+     */
+    Set<IParameterDelta> getParameterDeltas();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IFieldDelta.java b/tools/signature-tools/src/signature/compare/model/IFieldDelta.java
new file mode 100644
index 0000000..ab9bf76
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IFieldDelta.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import signature.model.IField;
+
+/**
+ * {@code IFieldDelta} models the delta between two {@link IField} instances.
+ */
+public interface IFieldDelta extends IMemberDelta<IField> {
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IGenericDeclarationDelta.java b/tools/signature-tools/src/signature/compare/model/IGenericDeclarationDelta.java
new file mode 100644
index 0000000..5cd518c
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IGenericDeclarationDelta.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import signature.model.IGenericDeclaration;
+
+/**
+ * {@code IGenericDeclarationDelta} models the delta between two
+ * {@link IGenericDeclaration} instances.
+ */
+public interface IGenericDeclarationDelta extends IDelta<IGenericDeclaration> {
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IMemberDelta.java b/tools/signature-tools/src/signature/compare/model/IMemberDelta.java
new file mode 100644
index 0000000..df78307
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IMemberDelta.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import java.util.Set;
+
+import signature.model.IField;
+
+/**
+ * {@code IMemberDelta} models the delta between two {@link IField} subclass
+ * instances.
+ */
+public interface IMemberDelta<T extends IField> extends IDelta<T>,
+        IAnnotatableElementDelta {
+
+    /**
+     * Returns a type delta or {@code null} if no delta is available.
+     * 
+     * @return a type delta, maybe {@code null}
+     */
+    ITypeReferenceDelta<?> getTypeDelta();
+
+    /**
+     * Returns a set of modifier deltas or {@code null} if no deltas are
+     * available.
+     * 
+     * @return a set of modifier deltas, maybe {@code null}
+     */
+    Set<IModifierDelta> getModifierDeltas();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IMethodDelta.java b/tools/signature-tools/src/signature/compare/model/IMethodDelta.java
new file mode 100644
index 0000000..3e94d26
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IMethodDelta.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import signature.model.IMethod;
+
+/**
+ * {@code IMethodDelta} models the delta between two {@link IMethod} subclass
+ * instances.
+ */
+public interface IMethodDelta extends IExecutableMemberDelta<IMethod> {
+
+    /**
+     * Returns a return type delta or {@code null} if no delta is available.
+     * 
+     * @return a return type delta, maybe {@code null}
+     */
+    ITypeReferenceDelta<?> getReturnTypeDelta();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IModifierDelta.java b/tools/signature-tools/src/signature/compare/model/IModifierDelta.java
new file mode 100644
index 0000000..4553e10
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IModifierDelta.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import signature.model.Modifier;
+
+/**
+ * {@code IModifierDelta} models the delta between two {@link Modifier}
+ * instances.
+ */
+public interface IModifierDelta extends IDelta<Modifier> {
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IPackageDelta.java b/tools/signature-tools/src/signature/compare/model/IPackageDelta.java
new file mode 100644
index 0000000..8c697c3
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IPackageDelta.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import java.util.Set;
+
+import signature.model.IPackage;
+
+/**
+ * {@code IPackageDelta} models the delta between two {@link IPackage}
+ * instances.
+ */
+public interface IPackageDelta extends IDelta<IPackage>,
+        IAnnotatableElementDelta {
+
+    /**
+     * Returns a set of class definition deltas or {@code null} if no deltas are
+     * available.
+     * 
+     * @return a set of class definition deltas, maybe {@code null}
+     */
+    Set<IClassDefinitionDelta> getClassDeltas();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IParameterDelta.java b/tools/signature-tools/src/signature/compare/model/IParameterDelta.java
new file mode 100644
index 0000000..b2a6a80
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IParameterDelta.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import signature.model.IParameter;
+
+/**
+ * {@code IParameterDelta} models the delta between two {@link IParameter}
+ * instances.
+ */
+public interface IParameterDelta extends IDelta<IParameter>,
+        IAnnotatableElementDelta {
+
+    /**
+     * Returns a parameter type delta or {@code null} if no delta is available.
+     * 
+     * @return a parameter type delta, maybe {@code null}
+     */
+    public ITypeReferenceDelta<?> getTypeDelta();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IParameterizedTypeDelta.java b/tools/signature-tools/src/signature/compare/model/IParameterizedTypeDelta.java
new file mode 100644
index 0000000..be54a01
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IParameterizedTypeDelta.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import java.util.Set;
+
+import signature.model.IParameterizedType;
+
+/**
+ * {@code IParameterizedTypeDelta} models the delta between two
+ * {@link IParameterizedType} instances.
+ */
+public interface IParameterizedTypeDelta extends
+        ITypeReferenceDelta<IParameterizedType> {
+
+    /**
+     * Returns a raw type delta or {@code null} if no delta is available.
+     * 
+     * @return a raw type delta, maybe {@code null}
+     */
+    ITypeReferenceDelta<?> getRawTypeDelta();
+
+    /**
+     * Returns a owner type delta or {@code null} if no delta is available.
+     * 
+     * @return a owner type delta, maybe {@code null}
+     */
+    ITypeReferenceDelta<?> getOwnerTypeDelta();
+
+    /**
+     * Returns a set of argument type deltas or {@code null} if no deltas are
+     * available.
+     * 
+     * @return a set of argument type deltas, maybe {@code null}
+     */
+    Set<ITypeReferenceDelta<?>> getArgumentTypeDeltas();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IPrimitiveTypeDelta.java b/tools/signature-tools/src/signature/compare/model/IPrimitiveTypeDelta.java
new file mode 100644
index 0000000..f729435
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IPrimitiveTypeDelta.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import signature.model.IPrimitiveType;
+
+/**
+ * {@code IPrimitiveTypeDelta} models the delta between two
+ * {@link IPrimitiveType} instances.
+ */
+public interface IPrimitiveTypeDelta extends
+        ITypeReferenceDelta<IPrimitiveType> {
+}
diff --git a/tools/signature-tools/src/signature/compare/model/ITypeDefinitionDelta.java b/tools/signature-tools/src/signature/compare/model/ITypeDefinitionDelta.java
new file mode 100644
index 0000000..932cc39
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/ITypeDefinitionDelta.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import signature.model.ITypeDefinition;
+
+/**
+ * {@code ITypeDefinitionDelta} is the common base interface for deltas which
+ * model differences between type definitions.
+ */
+public interface ITypeDefinitionDelta<T extends ITypeDefinition> extends
+        IDelta<T> {
+}
diff --git a/tools/signature-tools/src/signature/compare/model/ITypeReferenceDelta.java b/tools/signature-tools/src/signature/compare/model/ITypeReferenceDelta.java
new file mode 100644
index 0000000..fba52f0
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/ITypeReferenceDelta.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import signature.model.ITypeReference;
+
+/**
+ * {@code ITypeReferenceDelta} is the common base interface for deltas which
+ * model differences between type references.
+ */
+public interface ITypeReferenceDelta<T extends ITypeReference> extends
+        IDelta<T> {
+}
diff --git a/tools/signature-tools/src/signature/compare/model/ITypeVariableDefinitionDelta.java b/tools/signature-tools/src/signature/compare/model/ITypeVariableDefinitionDelta.java
new file mode 100644
index 0000000..1e8f3cd
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/ITypeVariableDefinitionDelta.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import signature.model.ITypeVariableDefinition;
+
+/**
+ * {@code ITypeVariableDefinitionDelta} models the delta between two
+ * {@link ITypeVariableDefinition} instances.
+ */
+public interface ITypeVariableDefinitionDelta extends
+        ITypeDefinitionDelta<ITypeVariableDefinition> {
+
+    /**
+     * Returns an upper bound delta or {@code null} if no delta is available.
+     * 
+     * @return an upper bound delta, maybe {@code null}
+     */
+    IUpperBoundsDelta getUpperBoundsDelta();
+
+    /**
+     * Returns a generic declaration delta or {@code null} if no delta is
+     * available.
+     * 
+     * @return a generic declaration delta, maybe {@code null}
+     */
+    IGenericDeclarationDelta getGenericDeclarationDelta();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/ITypeVariableDeltas.java b/tools/signature-tools/src/signature/compare/model/ITypeVariableDeltas.java
new file mode 100644
index 0000000..a88ea30
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/ITypeVariableDeltas.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import java.util.Set;
+
+/**
+ * Common interface for all deltas which may have {@code
+ * ITypeVariableDefinitionDelta}s. Type variable deltas can occur, where type
+ * variables can be defined. On classes, constructors and methods.
+ * 
+ * @see IClassDefinitionDelta
+ * @see IExecutableMemberDelta (common super interface of the following two
+ *      interfaces)
+ * @see IConstructorDelta
+ * @see IMethodDelta
+ */
+public interface ITypeVariableDeltas {
+
+    /**
+     * Returns a set of type variable deltas or {@code null} if no deltas are
+     * available.
+     * 
+     * @return a set of type variable deltas, maybe {@code null}
+     */
+    Set<ITypeVariableDefinitionDelta> getTypeVariableDeltas();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IUpperBoundsDelta.java b/tools/signature-tools/src/signature/compare/model/IUpperBoundsDelta.java
new file mode 100644
index 0000000..44bd39a
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IUpperBoundsDelta.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import java.util.List;
+import java.util.Set;
+
+import signature.model.ITypeReference;
+
+/**
+ * {@code IUpperBoundsDelta} models the delta between two {@link List
+ * &lt;ITypeReference&gt;} instances.
+ * <p>
+ * This interface is aware, that for the first argument, the order of the upper
+ * bounds is relevant (for erasure).
+ */
+public interface IUpperBoundsDelta extends IDelta<List<ITypeReference>> {
+    
+    /**
+     * Returns the upper bound delta of the first upper bound or {@code null} if
+     * no delta is available.
+     *
+     * @return the upper bound delta of the first upper bound, maybe {@code
+     *         null}
+     */
+    ITypeReferenceDelta<?> getFirstUpperBoundDelta();
+
+    /**
+     * Returns a set of remaining upper bound deltas or {@code null} if no
+     * deltas are available.
+     *
+     * @return a set of remaining upper bound deltas, maybe {@code null}
+     */
+    Set<ITypeReferenceDelta<?>> getRemainingUpperBoundDeltas();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/IValueDelta.java b/tools/signature-tools/src/signature/compare/model/IValueDelta.java
new file mode 100644
index 0000000..abd1f59
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IValueDelta.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+
+/**
+ * {@code IValueDelta} models the delta between two
+ * {@link Object} instances.
+ */
+public interface IValueDelta extends IDelta<Object> {}
diff --git a/tools/signature-tools/src/signature/compare/model/IWildcardTypeDelta.java b/tools/signature-tools/src/signature/compare/model/IWildcardTypeDelta.java
new file mode 100644
index 0000000..1fda09c
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/IWildcardTypeDelta.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model;
+
+import signature.model.IWildcardType;
+
+/**
+ * {@code IWildcardTypeDelta} models the delta between two
+ * {@link IWildcardType} instances.
+ */
+public interface IWildcardTypeDelta extends ITypeReferenceDelta<IWildcardType> {
+    
+    /**
+     * Returns the upper bound delta or {@code null} if no delta is available.
+     *
+     * @return the upper bound delta, maybe {@code null}
+     */
+    IUpperBoundsDelta getUpperBoundDelta();
+
+    /**
+     * Returns the lower bound delta or {@code null} if no delta is available.
+     *
+     * @return the lower bound delta, maybe {@code null}
+     */
+    ITypeReferenceDelta<?> getLowerBoundDelta();
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigAnnotationDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigAnnotationDelta.java
new file mode 100644
index 0000000..78e515f
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigAnnotationDelta.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import java.util.Set;
+
+import signature.compare.model.IAnnotationDelta;
+import signature.compare.model.IAnnotationElementDelta;
+import signature.model.IAnnotation;
+
+public class SigAnnotationDelta extends SigDelta<IAnnotation> implements
+        IAnnotationDelta {
+
+    private Set<IAnnotationElementDelta> annotationElementDeltas;
+
+    public SigAnnotationDelta(IAnnotation from, IAnnotation to) {
+        super(from, to);
+    }
+
+    public Set<IAnnotationElementDelta> getAnnotationElementDeltas() {
+        return annotationElementDeltas;
+    }
+
+    public void setAnnotationElementDeltas(
+            Set<IAnnotationElementDelta> annotationElementDeltas) {
+        this.annotationElementDeltas = annotationElementDeltas;
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigAnnotationElementDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigAnnotationElementDelta.java
new file mode 100644
index 0000000..cc7a6fc
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigAnnotationElementDelta.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.IAnnotationElementDelta;
+import signature.compare.model.IValueDelta;
+import signature.model.IAnnotationElement;
+
+public class SigAnnotationElementDelta extends SigDelta<IAnnotationElement>
+        implements IAnnotationElementDelta {
+
+    private IValueDelta valueDelta;
+
+    public SigAnnotationElementDelta(IAnnotationElement from,
+            IAnnotationElement to) {
+        super(from, to);
+    }
+
+    public IValueDelta getValueDelta() {
+        return valueDelta;
+    }
+
+    public void setValueDelta(IValueDelta valueDelta) {
+        this.valueDelta = valueDelta;
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigAnnotationFieldDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigAnnotationFieldDelta.java
new file mode 100644
index 0000000..90fcd7b
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigAnnotationFieldDelta.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.IAnnotationFieldDelta;
+import signature.compare.model.IValueDelta;
+import signature.model.IAnnotationField;
+
+public class SigAnnotationFieldDelta extends SigMemberDelta<IAnnotationField>
+        implements IAnnotationFieldDelta {
+
+    private IValueDelta defaultValueDelta;
+
+    public SigAnnotationFieldDelta(IAnnotationField from, IAnnotationField to) {
+        super(from, to);
+    }
+
+    public IValueDelta getDefaultValueDelta() {
+        return defaultValueDelta;
+    }
+
+    public void setDefaultValueDelta(IValueDelta valueDelta) {
+        this.defaultValueDelta = valueDelta;
+    }
+
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigApiDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigApiDelta.java
new file mode 100644
index 0000000..bc2bd56
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigApiDelta.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.IApiDelta;
+import signature.compare.model.IPackageDelta;
+import signature.model.IApi;
+
+import java.util.Set;
+
+public class SigApiDelta extends SigDelta<IApi> implements IApiDelta {
+
+    private Set<IPackageDelta> packageDeltas;
+
+    public SigApiDelta(IApi from, IApi to) {
+        super(from, to);
+    }
+
+    public Set<IPackageDelta> getPackageDeltas() {
+        return packageDeltas;
+    }
+
+    public void setPackageDeltas(Set<IPackageDelta> packageDeltas) {
+        this.packageDeltas = packageDeltas;
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigArrayTypeDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigArrayTypeDelta.java
new file mode 100644
index 0000000..5d47293
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigArrayTypeDelta.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.IArrayTypeDelta;
+import signature.compare.model.ITypeReferenceDelta;
+import signature.model.IArrayType;
+
+public class SigArrayTypeDelta extends SigTypeDelta<IArrayType> implements
+        IArrayTypeDelta {
+
+    private ITypeReferenceDelta<?> componentTypeDelta;
+
+    public SigArrayTypeDelta(IArrayType from, IArrayType to) {
+        super(from, to);
+    }
+
+    public ITypeReferenceDelta<?> getComponentTypeDelta() {
+        return componentTypeDelta;
+    }
+
+    public void setComponentTypeDelta(
+            ITypeReferenceDelta<?> componentTypeDelta) {
+        this.componentTypeDelta = componentTypeDelta;
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigClassDefinitionDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigClassDefinitionDelta.java
new file mode 100644
index 0000000..4034351
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigClassDefinitionDelta.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.IAnnotationDelta;
+import signature.compare.model.IAnnotationFieldDelta;
+import signature.compare.model.IClassDefinitionDelta;
+import signature.compare.model.IConstructorDelta;
+import signature.compare.model.IEnumConstantDelta;
+import signature.compare.model.IFieldDelta;
+import signature.compare.model.IMethodDelta;
+import signature.compare.model.IModifierDelta;
+import signature.compare.model.ITypeReferenceDelta;
+import signature.compare.model.ITypeVariableDefinitionDelta;
+import signature.model.IClassDefinition;
+
+import java.util.Set;
+
+public class SigClassDefinitionDelta extends
+        SigTypeDefinitionDelta<IClassDefinition> implements
+        IClassDefinitionDelta {
+
+    public SigClassDefinitionDelta(IClassDefinition from, IClassDefinition to) {
+        super(from, to);
+    }
+
+    private Set<IAnnotationFieldDelta> annotationFieldDeltas;
+    private Set<IConstructorDelta> constructorDeltas;
+    private Set<IEnumConstantDelta> enumConstantDeltas;
+    private Set<IFieldDelta> fieldDeltas;
+    private Set<ITypeReferenceDelta<?>> interfaceDeltas;
+    private Set<IMethodDelta> methodDeltas;
+    private Set<IModifierDelta> modifierDeltas;
+    private ITypeReferenceDelta<?> superClassDelta;
+    private Set<IAnnotationDelta> annotationDeltas;
+    private Set<ITypeVariableDefinitionDelta> typeVariableDeltas;
+
+    public Set<IAnnotationFieldDelta> getAnnotationFieldDeltas() {
+        return annotationFieldDeltas;
+    }
+
+    public void setAnnotationFieldDeltas(
+            Set<IAnnotationFieldDelta> annotationFieldDeltas) {
+        this.annotationFieldDeltas = annotationFieldDeltas;
+    }
+
+    public Set<IConstructorDelta> getConstructorDeltas() {
+        return constructorDeltas;
+    }
+
+    public void setConstructorDeltas(
+            Set<IConstructorDelta> constructorDeltas) {
+        this.constructorDeltas = constructorDeltas;
+    }
+
+    public Set<IEnumConstantDelta> getEnumConstantDeltas() {
+        return enumConstantDeltas;
+    }
+
+    public void setEnumConstantDeltas(
+            Set<IEnumConstantDelta> enumConstantDeltas) {
+        this.enumConstantDeltas = enumConstantDeltas;
+    }
+
+    public Set<IFieldDelta> getFieldDeltas() {
+        return fieldDeltas;
+    }
+
+    public void setFieldDeltas(Set<IFieldDelta> fieldDeltas) {
+        this.fieldDeltas = fieldDeltas;
+    }
+
+    public Set<ITypeReferenceDelta<?>> getInterfaceDeltas() {
+        return interfaceDeltas;
+    }
+
+    public void setInterfaceDeltas(
+            Set<ITypeReferenceDelta<?>> interfaceDeltas) {
+        this.interfaceDeltas = interfaceDeltas;
+    }
+
+    public Set<IMethodDelta> getMethodDeltas() {
+        return methodDeltas;
+    }
+
+    public void setMethodDeltas(Set<IMethodDelta> methodDeltas) {
+        this.methodDeltas = methodDeltas;
+    }
+
+    public Set<IModifierDelta> getModifierDeltas() {
+        return modifierDeltas;
+    }
+
+    public void setModifierDeltas(Set<IModifierDelta> modifierDeltas) {
+        this.modifierDeltas = modifierDeltas;
+    }
+
+    public ITypeReferenceDelta<?> getSuperClassDelta() {
+        return superClassDelta;
+    }
+
+    public void setSuperClassDelta(ITypeReferenceDelta<?> superClassDelta) {
+        this.superClassDelta = superClassDelta;
+    }
+
+    public Set<IAnnotationDelta> getAnnotationDeltas() {
+        return annotationDeltas;
+    }
+
+    public void setAnnotationDeltas(Set<IAnnotationDelta> annotationDeltas) {
+        this.annotationDeltas = annotationDeltas;
+    }
+
+    public Set<ITypeVariableDefinitionDelta> getTypeVariableDeltas() {
+        return typeVariableDeltas;
+    }
+
+    public void setTypeVariableDeltas(
+            Set<ITypeVariableDefinitionDelta> typeVariableDeltas) {
+        this.typeVariableDeltas = typeVariableDeltas;
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigClassReferenceDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigClassReferenceDelta.java
new file mode 100644
index 0000000..18741eb
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigClassReferenceDelta.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.ITypeReferenceDelta;
+import signature.model.IClassReference;
+
+public class SigClassReferenceDelta extends SigDelta<IClassReference>
+        implements ITypeReferenceDelta<IClassReference> {
+
+    public SigClassReferenceDelta(IClassReference from, IClassReference to) {
+        super(from, to);
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigConstructorDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigConstructorDelta.java
new file mode 100644
index 0000000..9a7cf70
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigConstructorDelta.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.IConstructorDelta;
+import signature.model.IConstructor;
+
+public class SigConstructorDelta extends SigExecutableMemberDelta<IConstructor>
+        implements IConstructorDelta {
+
+    public SigConstructorDelta(IConstructor from, IConstructor to) {
+        super(from, to);
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigDelta.java
new file mode 100644
index 0000000..933bf00
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigDelta.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import signature.compare.model.IDelta;
+import signature.compare.model.DeltaType;
+
+public abstract class SigDelta<T> implements IDelta<T> {
+    private T from;
+    private T to;
+
+    public SigDelta(T from, T to) {
+        this.from = from;
+        this.to = to;
+    }
+
+    public final T getFrom() {
+        return from;
+    }
+
+    public final T getTo() {
+        return to;
+    }
+
+    public final DeltaType getType() {
+        if (from == null && to != null) {
+            return DeltaType.ADDED;
+        }
+        if (from != null && to == null) {
+            return DeltaType.REMOVED;
+        }
+        return DeltaType.CHANGED;
+    }
+
+    private static <T extends IDelta<?>> Set<T> getDeltas(Set<T> deltas,
+            DeltaType type) {
+        Set<T> addedElements = new HashSet<T>();
+        for (T delta : deltas) {
+            if (type.equals(delta.getType())) {
+                addedElements.add(delta);
+            }
+        }
+        return addedElements;
+    }
+
+    public static <T extends IDelta<?>> Set<T> getAdded(Set<T> deltas) {
+        return getDeltas(deltas, DeltaType.ADDED);
+    }
+
+    public static <T extends IDelta<?>> Set<T> getRemoved(Set<T> deltas) {
+        return getDeltas(deltas, DeltaType.REMOVED);
+    }
+
+    public static <T extends IDelta<?>> Set<T> getChanged(Set<T> deltas) {
+        return getDeltas(deltas, DeltaType.CHANGED);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append(getClass().getSimpleName());
+        builder.append(":\n");
+
+        List<Field> allFields = new LinkedList<Field>();
+
+        Class<?> actualClass = getClass();
+
+        // add all fields / super classes also
+        do {
+            allFields.addAll(Arrays.asList(actualClass.getDeclaredFields()));
+            actualClass = actualClass.getSuperclass();
+        } while (actualClass != Object.class);
+
+        builder.append("from: ");
+        builder.append(from);
+        builder.append("\nto:    ");
+        builder.append(to);
+        builder.append("\n");
+        try {
+            for (Field field : allFields) {
+                if (!ignore.contains(field.getName())) {
+                    field.setAccessible(true);
+                    Object delta = field.get(this);
+                    if (delta != null) {
+                        builder.append(field.getName());
+                        builder.append(":\n");
+                        builder.append(delta);
+                    }
+                }
+            }
+        } catch (IllegalArgumentException e) {
+            e.printStackTrace();
+        } catch (IllegalAccessException e) {
+            e.printStackTrace();
+        } catch (SecurityException e) {
+            e.printStackTrace();
+        }
+
+        return builder.toString();
+    }
+
+    private static Set<String> ignore = new HashSet<String>();
+    {
+        ignore.add("from");
+        ignore.add("to");
+        ignore.add("reason");
+        ignore.add("ignore"); // =)
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigEnumConstantDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigEnumConstantDelta.java
new file mode 100644
index 0000000..3a7f9e7
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigEnumConstantDelta.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.IEnumConstantDelta;
+import signature.compare.model.IValueDelta;
+import signature.model.IEnumConstant;
+
+public class SigEnumConstantDelta extends SigMemberDelta<IEnumConstant>
+        implements IEnumConstantDelta {
+
+    private IValueDelta ordinalDelta;
+
+    public SigEnumConstantDelta(IEnumConstant from, IEnumConstant to) {
+        super(from, to);
+    }
+
+    public IValueDelta getOrdinalDelta() {
+        return ordinalDelta;
+    }
+
+    public void setOrdinalDelta(IValueDelta ordinalDelta) {
+        this.ordinalDelta = ordinalDelta;
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigExecutableMemberDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigExecutableMemberDelta.java
new file mode 100644
index 0000000..1d871e4
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigExecutableMemberDelta.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.IAnnotationDelta;
+import signature.compare.model.IExecutableMemberDelta;
+import signature.compare.model.IModifierDelta;
+import signature.compare.model.IParameterDelta;
+import signature.compare.model.ITypeReferenceDelta;
+import signature.compare.model.ITypeVariableDefinitionDelta;
+import signature.model.IExecutableMember;
+
+import java.util.Set;
+
+public abstract class SigExecutableMemberDelta<T extends IExecutableMember>
+        extends SigDelta<T> implements IExecutableMemberDelta<T> {
+
+    private Set<ITypeReferenceDelta<?>> exceptionDeltas;
+    private Set<IModifierDelta> modifierDeltas;
+    private Set<ITypeVariableDefinitionDelta> typeVariableDeltas;
+    private Set<IAnnotationDelta> annotationDeltas;
+    private Set<IParameterDelta> parameterDeltas;
+
+    public SigExecutableMemberDelta(T from, T to) {
+        super(from, to);
+    }
+
+    public Set<ITypeReferenceDelta<?>> getExceptionDeltas() {
+        return exceptionDeltas;
+    }
+
+    public void setExceptionDeltas(
+            Set<ITypeReferenceDelta<?>> exceptionDeltas) {
+        this.exceptionDeltas = exceptionDeltas;
+    }
+
+    public Set<IModifierDelta> getModifierDeltas() {
+        return modifierDeltas;
+    }
+
+    public void setModifierDeltas(Set<IModifierDelta> modifierDeltas) {
+        this.modifierDeltas = modifierDeltas;
+    }
+
+    public Set<ITypeVariableDefinitionDelta> getTypeVariableDeltas() {
+        return typeVariableDeltas;
+    }
+
+    public void setTypeVariableDeltas(
+            Set<ITypeVariableDefinitionDelta> typeVariableDeltas) {
+        this.typeVariableDeltas = typeVariableDeltas;
+    }
+
+    public Set<IAnnotationDelta> getAnnotationDeltas() {
+        return annotationDeltas;
+    }
+
+    public void setAnnotationDeltas(Set<IAnnotationDelta> annotationDeltas) {
+        this.annotationDeltas = annotationDeltas;
+    }
+
+    public Set<IParameterDelta> getParameterDeltas() {
+        return parameterDeltas;
+    }
+
+    public void setParameterDeltas(Set<IParameterDelta> parameterDeltas) {
+        this.parameterDeltas = parameterDeltas;
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigFieldDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigFieldDelta.java
new file mode 100644
index 0000000..6807eea
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigFieldDelta.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.IFieldDelta;
+import signature.model.IField;
+
+public class SigFieldDelta extends SigMemberDelta<IField> implements
+        IFieldDelta {
+
+    public SigFieldDelta(IField from, IField to) {
+        super(from, to);
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigGenericDeclarationDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigGenericDeclarationDelta.java
new file mode 100644
index 0000000..d377b95
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigGenericDeclarationDelta.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.IGenericDeclarationDelta;
+import signature.model.IGenericDeclaration;
+
+public class SigGenericDeclarationDelta extends SigDelta<IGenericDeclaration>
+        implements IGenericDeclarationDelta {
+
+    public SigGenericDeclarationDelta(IGenericDeclaration from,
+            IGenericDeclaration to) {
+        super(from, to);
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigMemberDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigMemberDelta.java
new file mode 100644
index 0000000..2c5e9cb
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigMemberDelta.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import java.util.Set;
+
+import signature.compare.model.IAnnotationDelta;
+import signature.compare.model.IMemberDelta;
+import signature.compare.model.IModifierDelta;
+import signature.compare.model.ITypeReferenceDelta;
+import signature.model.IField;
+
+public abstract class SigMemberDelta<T extends IField> extends SigDelta<T>
+        implements IMemberDelta<T> {
+
+    private Set<IModifierDelta> modifierDeltas;
+    private ITypeReferenceDelta<?> typeDelta;
+    private Set<IAnnotationDelta> annotationDeltas;
+
+
+    public SigMemberDelta(T from, T to) {
+        super(from, to);
+    }
+
+    public Set<IModifierDelta> getModifierDeltas() {
+        return modifierDeltas;
+    }
+
+    public void setModifierDeltas(Set<IModifierDelta> modifierDeltas) {
+        this.modifierDeltas = modifierDeltas;
+    }
+
+    public ITypeReferenceDelta<?> getTypeDelta() {
+        return typeDelta;
+    }
+
+    public void setTypeDelta(ITypeReferenceDelta<?> typeDelta) {
+        this.typeDelta = typeDelta;
+    }
+
+    public Set<IAnnotationDelta> getAnnotationDeltas() {
+        return annotationDeltas;
+    }
+
+    public void setAnnotationDeltas(Set<IAnnotationDelta> annotationDeltas) {
+        this.annotationDeltas = annotationDeltas;
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigMethodDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigMethodDelta.java
new file mode 100644
index 0000000..0a3fb2f
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigMethodDelta.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.IMethodDelta;
+import signature.compare.model.ITypeReferenceDelta;
+import signature.model.IMethod;
+
+public class SigMethodDelta extends SigExecutableMemberDelta<IMethod> implements
+        IMethodDelta {
+
+    private ITypeReferenceDelta<?> returnTypeDelta;
+
+    public SigMethodDelta(IMethod from, IMethod to) {
+        super(from, to);
+    }
+
+    public ITypeReferenceDelta<?> getReturnTypeDelta() {
+        return returnTypeDelta;
+    }
+
+    public void setReturnTypeDelta(ITypeReferenceDelta<?> returnTypeDelta) {
+        this.returnTypeDelta = returnTypeDelta;
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigModifierDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigModifierDelta.java
new file mode 100644
index 0000000..aa5e380
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigModifierDelta.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.IModifierDelta;
+import signature.model.Modifier;
+
+public class SigModifierDelta extends SigDelta<Modifier> implements
+        IModifierDelta {
+
+    public SigModifierDelta(Modifier from, Modifier to) {
+        super(from, to);
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigPackageDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigPackageDelta.java
new file mode 100644
index 0000000..0f368f6
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigPackageDelta.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import java.util.Set;
+
+import signature.compare.model.IAnnotationDelta;
+import signature.compare.model.IClassDefinitionDelta;
+import signature.compare.model.IPackageDelta;
+import signature.model.IPackage;
+
+public class SigPackageDelta extends SigDelta<IPackage> implements
+        IPackageDelta {
+
+    private Set<IClassDefinitionDelta> classDeltas;
+    private Set<IAnnotationDelta> annotationDeltas;
+
+    public SigPackageDelta(IPackage from, IPackage to) {
+        super(from, to);
+    }
+
+    public Set<IClassDefinitionDelta> getClassDeltas() {
+        return classDeltas;
+    }
+
+    public void setClassDeltas(Set<IClassDefinitionDelta> classDeltas) {
+        this.classDeltas = classDeltas;
+    }
+
+    public Set<IAnnotationDelta> getAnnotationDeltas() {
+        return annotationDeltas;
+    }
+
+    public void setAnnotationDeltas(Set<IAnnotationDelta> annotationDeltas) {
+        this.annotationDeltas = annotationDeltas;
+    }
+
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigParameterDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigParameterDelta.java
new file mode 100644
index 0000000..aee6466
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigParameterDelta.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import java.util.Set;
+
+import signature.compare.model.IAnnotationDelta;
+import signature.compare.model.IParameterDelta;
+import signature.compare.model.ITypeReferenceDelta;
+import signature.model.IParameter;
+
+public class SigParameterDelta extends SigDelta<IParameter> implements
+        IParameterDelta {
+
+    private ITypeReferenceDelta<?> typeDelta;
+    private Set<IAnnotationDelta> annotationDeltas;
+
+    public SigParameterDelta(IParameter from, IParameter to) {
+        super(from, to);
+    }
+
+    public ITypeReferenceDelta<?> getTypeDelta() {
+        return typeDelta;
+    }
+
+    public void setTypeDelta(ITypeReferenceDelta<?> typeDelta) {
+        this.typeDelta = typeDelta;
+    }
+
+    public Set<IAnnotationDelta> getAnnotationDeltas() {
+        return annotationDeltas;
+    }
+
+    public void setAnnotationDeltas(Set<IAnnotationDelta> annotationDeltas) {
+        this.annotationDeltas = annotationDeltas;
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigParameterizedTypeDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigParameterizedTypeDelta.java
new file mode 100644
index 0000000..08fbc21
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigParameterizedTypeDelta.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import java.util.Set;
+
+import signature.compare.model.IParameterizedTypeDelta;
+import signature.compare.model.ITypeReferenceDelta;
+import signature.model.IParameterizedType;
+
+public class SigParameterizedTypeDelta extends SigTypeDelta<IParameterizedType>
+        implements IParameterizedTypeDelta {
+
+    private ITypeReferenceDelta<?> ownerTypeDelta;
+    private ITypeReferenceDelta<?> rawTypeDelta;
+    private Set<ITypeReferenceDelta<?>> argumentTypeDeltas;
+
+    public SigParameterizedTypeDelta(IParameterizedType from,
+            IParameterizedType to) {
+        super(from, to);
+    }
+
+    public ITypeReferenceDelta<?> getOwnerTypeDelta() {
+        return ownerTypeDelta;
+    }
+
+    public void setOwnerTypeDelta(ITypeReferenceDelta<?> ownerTypeDelta) {
+        this.ownerTypeDelta = ownerTypeDelta;
+    }
+
+    public ITypeReferenceDelta<?> getRawTypeDelta() {
+        return rawTypeDelta;
+    }
+
+    public void setRawTypeDelta(ITypeReferenceDelta<?> rawTypeDelta) {
+        this.rawTypeDelta = rawTypeDelta;
+    }
+
+    public Set<ITypeReferenceDelta<?>> getArgumentTypeDeltas() {
+        return argumentTypeDeltas;
+    }
+
+    public void setArgumentTypeDeltas(
+            Set<ITypeReferenceDelta<?>> argumentTypeDeltas) {
+        this.argumentTypeDeltas = argumentTypeDeltas;
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigPrimitiveTypeDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigPrimitiveTypeDelta.java
new file mode 100644
index 0000000..03be8fa
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigPrimitiveTypeDelta.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.IPrimitiveTypeDelta;
+import signature.model.IPrimitiveType;
+
+public class SigPrimitiveTypeDelta extends SigTypeDelta<IPrimitiveType>
+        implements IPrimitiveTypeDelta {
+
+    public SigPrimitiveTypeDelta(IPrimitiveType from, IPrimitiveType to) {
+        super(from, to);
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigTypeDefinitionDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigTypeDefinitionDelta.java
new file mode 100644
index 0000000..c0bff8e
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigTypeDefinitionDelta.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.ITypeDefinitionDelta;
+import signature.model.ITypeDefinition;
+
+public abstract class SigTypeDefinitionDelta<T extends ITypeDefinition> extends
+        SigDelta<T> implements ITypeDefinitionDelta<T> {
+
+    public SigTypeDefinitionDelta(T from, T to) {
+        super(from, to);
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigTypeDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigTypeDelta.java
new file mode 100644
index 0000000..718258c
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigTypeDelta.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.ITypeReferenceDelta;
+import signature.model.ITypeReference;
+
+public class SigTypeDelta<T extends ITypeReference> extends SigDelta<T>
+        implements ITypeReferenceDelta<T> {
+
+    public SigTypeDelta(T from, T to) {
+        super(from, to);
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigTypeVariableDefinitionDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigTypeVariableDefinitionDelta.java
new file mode 100644
index 0000000..348c728
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigTypeVariableDefinitionDelta.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.IGenericDeclarationDelta;
+import signature.compare.model.ITypeVariableDefinitionDelta;
+import signature.compare.model.IUpperBoundsDelta;
+import signature.model.ITypeVariableDefinition;
+
+public class SigTypeVariableDefinitionDelta extends
+        SigDelta<ITypeVariableDefinition> implements
+        ITypeVariableDefinitionDelta {
+
+    private IUpperBoundsDelta upperBoundsDelta;
+    private IGenericDeclarationDelta genericDeclarationDelta;
+
+    public SigTypeVariableDefinitionDelta(ITypeVariableDefinition from,
+            ITypeVariableDefinition to) {
+        super(from, to);
+    }
+
+    public IUpperBoundsDelta getUpperBoundsDelta() {
+        return upperBoundsDelta;
+    }
+
+    public void setUpperBoundsDelta(IUpperBoundsDelta upperBoundsDelta) {
+        this.upperBoundsDelta = upperBoundsDelta;
+    }
+
+    public IGenericDeclarationDelta getGenericDeclarationDelta() {
+        return genericDeclarationDelta;
+    }
+
+    public void setGenericDeclarationDelta(
+            IGenericDeclarationDelta genericDeclarationDelta) {
+        this.genericDeclarationDelta = genericDeclarationDelta;
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigTypeVariableReferenceDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigTypeVariableReferenceDelta.java
new file mode 100644
index 0000000..4414a16
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigTypeVariableReferenceDelta.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.IGenericDeclarationDelta;
+import signature.compare.model.ITypeReferenceDelta;
+import signature.model.ITypeVariableReference;
+
+public class SigTypeVariableReferenceDelta extends
+        SigDelta<ITypeVariableReference> implements
+        ITypeReferenceDelta<ITypeVariableReference> {
+
+    private IGenericDeclarationDelta genericDeclarationDelta;
+
+    public SigTypeVariableReferenceDelta(ITypeVariableReference from,
+            ITypeVariableReference to) {
+        super(from, to);
+    }
+
+    public IGenericDeclarationDelta getGenericDeclarationDelta() {
+        return genericDeclarationDelta;
+    }
+
+    public void setGenericDeclarationDelta(
+            IGenericDeclarationDelta genericDeclarationDelta) {
+        this.genericDeclarationDelta = genericDeclarationDelta;
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigUpperBoundsDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigUpperBoundsDelta.java
new file mode 100644
index 0000000..8822b26
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigUpperBoundsDelta.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import java.util.List;
+import java.util.Set;
+
+import signature.compare.model.ITypeReferenceDelta;
+import signature.compare.model.IUpperBoundsDelta;
+import signature.model.ITypeReference;
+
+public class SigUpperBoundsDelta extends SigDelta<List<ITypeReference>>
+        implements IUpperBoundsDelta {
+
+    private ITypeReferenceDelta<?> firstUpperBoundDelta;
+    private Set<ITypeReferenceDelta<?>> remainingUpperBoundDeltas;
+
+    public SigUpperBoundsDelta(List<ITypeReference> from,
+            List<ITypeReference> to) {
+        super(from, to);
+    }
+
+
+    public ITypeReferenceDelta<?> getFirstUpperBoundDelta() {
+        return firstUpperBoundDelta;
+    }
+
+    public void setFirstUpperBoundDelta(
+            ITypeReferenceDelta<?> firstUpperBoundDelta) {
+        this.firstUpperBoundDelta = firstUpperBoundDelta;
+    }
+
+    public Set<ITypeReferenceDelta<?>> getRemainingUpperBoundDeltas() {
+        return remainingUpperBoundDeltas;
+    }
+
+    public void setRemainingUpperBoundDeltas(
+            Set<ITypeReferenceDelta<?>> remainingUpperBoundDeltas) {
+        this.remainingUpperBoundDeltas = remainingUpperBoundDeltas;
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigValueDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigValueDelta.java
new file mode 100644
index 0000000..9521f0e
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigValueDelta.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.IValueDelta;
+
+public class SigValueDelta extends SigDelta<Object> implements IValueDelta {
+
+    public SigValueDelta(Object from, Object to) {
+        super(from, to);
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/impl/SigWildcardTypeDelta.java b/tools/signature-tools/src/signature/compare/model/impl/SigWildcardTypeDelta.java
new file mode 100644
index 0000000..e6cafcb
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/impl/SigWildcardTypeDelta.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.impl;
+
+import signature.compare.model.ITypeReferenceDelta;
+import signature.compare.model.IUpperBoundsDelta;
+import signature.compare.model.IWildcardTypeDelta;
+import signature.model.IWildcardType;
+
+public class SigWildcardTypeDelta extends SigTypeDelta<IWildcardType>
+        implements IWildcardTypeDelta {
+
+    private ITypeReferenceDelta<?> lowerBoundDelta;
+    private IUpperBoundsDelta upperBoundDelta;
+
+    public SigWildcardTypeDelta(IWildcardType from, IWildcardType to) {
+        super(from, to);
+    }
+
+    public ITypeReferenceDelta<?> getLowerBoundDelta() {
+        return lowerBoundDelta;
+    }
+
+    public void setLowerBoundDelta(ITypeReferenceDelta<?> lowerBoundDelta) {
+        this.lowerBoundDelta = lowerBoundDelta;
+    }
+
+    public IUpperBoundsDelta getUpperBoundDelta() {
+        return upperBoundDelta;
+    }
+
+    public void setUpperBoundDelta(IUpperBoundsDelta upperBoundDelta) {
+        this.upperBoundDelta = upperBoundDelta;
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/subst/ArrayTypeProjection.java b/tools/signature-tools/src/signature/compare/model/subst/ArrayTypeProjection.java
new file mode 100644
index 0000000..428146e
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/subst/ArrayTypeProjection.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.subst;
+
+import java.util.Map;
+
+import signature.model.IArrayType;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+import signature.model.impl.SigArrayType;
+
+public class ArrayTypeProjection implements IArrayType {
+
+    private final IArrayType original;
+    private final Map<ITypeVariableDefinition, ITypeReference> mappings;
+
+    public ArrayTypeProjection(IArrayType original,
+            Map<ITypeVariableDefinition, ITypeReference> mappings) {
+        this.original = original;
+        this.mappings = mappings;
+    }
+
+    public ITypeReference getComponentType() {
+        return ViewpointAdapter.substitutedTypeReference(original
+                .getComponentType(), mappings);
+    }
+
+    @Override
+    public int hashCode() {
+        return SigArrayType.hashCode(this);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return SigArrayType.equals(this, obj);
+    }
+
+    @Override
+    public String toString() {
+        return "(" + SigArrayType.toString(this) + " : " + mappings + " )";
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/subst/ClassProjection.java b/tools/signature-tools/src/signature/compare/model/subst/ClassProjection.java
new file mode 100644
index 0000000..630d102
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/subst/ClassProjection.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.subst;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import signature.model.IAnnotation;
+import signature.model.IAnnotationField;
+import signature.model.IClassDefinition;
+import signature.model.IConstructor;
+import signature.model.IEnumConstant;
+import signature.model.IField;
+import signature.model.IMethod;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+import signature.model.Kind;
+import signature.model.Modifier;
+import signature.model.impl.SigClassDefinition;
+
+public class ClassProjection implements IClassDefinition {
+
+    private final IClassDefinition original;
+    private final Map<ITypeVariableDefinition, ITypeReference> substitutions;
+
+    public ClassProjection(IClassDefinition original,
+            Map<ITypeVariableDefinition, ITypeReference> mapping) {
+        this.original = original;
+        this.substitutions = mapping;
+    }
+
+    public Set<IAnnotationField> getAnnotationFields() {
+        throw new UnsupportedOperationException();
+    }
+
+    public Set<IAnnotation> getAnnotations() {
+        throw new UnsupportedOperationException();
+    }
+
+    public Set<IConstructor> getConstructors() {
+        throw new UnsupportedOperationException();
+    }
+
+    public IClassDefinition getDeclaringClass() {
+        throw new UnsupportedOperationException();
+    }
+
+    public Set<IEnumConstant> getEnumConstants() {
+        throw new UnsupportedOperationException();
+    }
+
+    public Set<IField> getFields() {
+        throw new UnsupportedOperationException();
+    }
+
+    public Set<IClassDefinition> getInnerClasses() {
+        throw new UnsupportedOperationException();
+    }
+
+    Set<ITypeReference> interfaces = null;
+
+    public Set<ITypeReference> getInterfaces() {
+        if (interfaces == null) {
+            Set<ITypeReference> originalInterfaces = original.getInterfaces();
+            if (originalInterfaces == null) {
+                interfaces = Collections.emptySet();
+            } else {
+                interfaces = new HashSet<ITypeReference>();
+                for (ITypeReference interfaze : originalInterfaces) {
+                    interfaces.add(ViewpointAdapter.substitutedTypeReference(
+                            interfaze, substitutions));
+                }
+                interfaces = Collections.unmodifiableSet(interfaces);
+            }
+        }
+        return interfaces;
+    }
+
+    public Kind getKind() {
+        return original.getKind();
+    }
+
+
+    Set<IMethod> methods = null;
+
+    public Set<IMethod> getMethods() {
+        if (methods == null) {
+            Set<IMethod> originalMethods = original.getMethods();
+            if (originalMethods == null) {
+                methods = Collections.emptySet();
+            } else {
+                methods = new HashSet<IMethod>();
+                for (IMethod m : original.getMethods()) {
+                    methods.add(new MethodProjection(m, substitutions));
+                }
+                methods = Collections.unmodifiableSet(methods);
+            }
+        }
+        return methods;
+    }
+
+    public Set<Modifier> getModifiers() {
+        return original.getModifiers();
+    }
+
+    public String getName() {
+        return original.getName();
+    }
+
+    public List<String> getPackageFragments() {
+        return original.getPackageFragments();
+    }
+
+    public String getPackageName() {
+        return original.getPackageName();
+    }
+
+    public String getQualifiedName() {
+        return original.getQualifiedName();
+    }
+
+    private boolean superClassInit = false;
+    private ITypeReference superClass = null;
+
+    public ITypeReference getSuperClass() {
+        if (!superClassInit) {
+            ITypeReference originalSuperClass = original.getSuperClass();
+            if (originalSuperClass != null) {
+                superClass = ViewpointAdapter.substitutedTypeReference(original
+                        .getSuperClass(), substitutions);
+            }
+            superClassInit = true;
+        }
+        return superClass;
+    }
+
+    // Definitions of type variables are not substituted
+    public List<ITypeVariableDefinition> getTypeParameters() {
+        return original.getTypeParameters();
+    }
+
+    @Override
+    public int hashCode() {
+        return SigClassDefinition.hashCode(this);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return SigClassDefinition.equals(this, obj);
+    }
+
+    @Override
+    public String toString() {
+        return "(" + SigClassDefinition.toString(this) + " : " + substitutions
+                + " )";
+    }
+
+}
diff --git a/tools/signature-tools/src/signature/compare/model/subst/ClassReferenceProjection.java b/tools/signature-tools/src/signature/compare/model/subst/ClassReferenceProjection.java
new file mode 100644
index 0000000..648ccf8
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/subst/ClassReferenceProjection.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.subst;
+
+import signature.model.IClassDefinition;
+import signature.model.IClassReference;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+import signature.model.impl.SigClassReference;
+
+import java.util.Map;
+
+public class ClassReferenceProjection implements IClassReference {
+
+    private final IClassReference original;
+    private final Map<ITypeVariableDefinition, ITypeReference> mappings;
+
+    public ClassReferenceProjection(IClassReference original,
+            Map<ITypeVariableDefinition, ITypeReference> mappings) {
+        this.original = original;
+        this.mappings = mappings;
+    }
+
+    public IClassDefinition getClassDefinition() {
+        return new ClassProjection(original.getClassDefinition(), mappings);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return SigClassReference.equals(this, obj);
+    }
+
+    @Override
+    public int hashCode() {
+        return SigClassReference.hashCode(this);
+    }
+
+    @Override
+    public String toString() {
+        return "(" + SigClassReference.toString(this) + " : " + mappings + " )";
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/subst/ConstructorProjection.java b/tools/signature-tools/src/signature/compare/model/subst/ConstructorProjection.java
new file mode 100644
index 0000000..1ffd616
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/subst/ConstructorProjection.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.subst;
+
+import signature.model.IConstructor;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+
+import java.util.Map;
+
+public class ConstructorProjection extends ExecutableMemberProjection implements
+        IConstructor {
+
+    public ConstructorProjection(IConstructor original,
+            Map<ITypeVariableDefinition, ITypeReference> mappings) {
+        super(original, mappings);
+    }
+
+}
diff --git a/tools/signature-tools/src/signature/compare/model/subst/ExecutableMemberProjection.java b/tools/signature-tools/src/signature/compare/model/subst/ExecutableMemberProjection.java
new file mode 100644
index 0000000..f96ac54
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/subst/ExecutableMemberProjection.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.subst;
+
+import signature.model.IAnnotation;
+import signature.model.IClassDefinition;
+import signature.model.IExecutableMember;
+import signature.model.IParameter;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+import signature.model.Modifier;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public abstract class ExecutableMemberProjection implements IExecutableMember {
+
+    private final IExecutableMember original;
+    private final Map<ITypeVariableDefinition, ITypeReference> mappings;
+
+    public ExecutableMemberProjection(IExecutableMember original,
+            Map<ITypeVariableDefinition, ITypeReference> mappings) {
+        this.original = original;
+        this.mappings = mappings;
+    }
+
+    public Set<IAnnotation> getAnnotations() {
+        return original.getAnnotations();
+    }
+
+    public IClassDefinition getDeclaringClass() {
+        throw new UnsupportedOperationException();
+    }
+
+    public Set<ITypeReference> getExceptions() {
+        return ViewpointAdapter.substitutedTypeReferences(original
+                .getExceptions(), mappings);
+    }
+
+    public Set<Modifier> getModifiers() {
+        return original.getModifiers();
+    }
+
+    public String getName() {
+        return original.getName();
+    }
+
+    public List<IParameter> getParameters() {
+        List<IParameter> result = new LinkedList<IParameter>();
+        for (IParameter parameter : original.getParameters()) {
+            result.add(new ParameterProjection(parameter, mappings));
+        }
+        return result;
+    }
+
+    public List<ITypeVariableDefinition> getTypeParameters() {
+        // FIXME bounds need to be substituted ?
+        return original.getTypeParameters();
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/subst/MethodProjection.java b/tools/signature-tools/src/signature/compare/model/subst/MethodProjection.java
new file mode 100644
index 0000000..c98fb09
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/subst/MethodProjection.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.subst;
+
+import signature.model.IMethod;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+import signature.model.impl.SigMethod;
+
+import java.util.Map;
+
+public class MethodProjection extends ExecutableMemberProjection implements
+        IMethod {
+
+    private final IMethod original;
+    private Map<ITypeVariableDefinition, ITypeReference> mappings;
+
+    public MethodProjection(IMethod original,
+            Map<ITypeVariableDefinition, ITypeReference> mappings) {
+        super(original, mappings);
+        this.mappings = mappings;
+        this.original = original;
+    }
+
+    public ITypeReference getReturnType() {
+        return ViewpointAdapter.substitutedTypeReference(original
+                .getReturnType(), mappings);
+    }
+
+    @Override
+    public String toString() {
+        return "(" + SigMethod.toString(this) + " : " + mappings + " )";
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/subst/ParameterProjection.java b/tools/signature-tools/src/signature/compare/model/subst/ParameterProjection.java
new file mode 100644
index 0000000..9c48ab7
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/subst/ParameterProjection.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.subst;
+
+import signature.model.IAnnotation;
+import signature.model.IParameter;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+
+import java.util.Map;
+import java.util.Set;
+
+public class ParameterProjection implements IParameter {
+    private IParameter original;
+    private Map<ITypeVariableDefinition, ITypeReference> mappings;
+
+    public ParameterProjection(IParameter original,
+            Map<ITypeVariableDefinition, ITypeReference> mappings) {
+        this.original = original;
+        this.mappings = mappings;
+    }
+
+    public Set<IAnnotation> getAnnotations() {
+        return original.getAnnotations();
+    }
+
+    public ITypeReference getType() {
+        return ViewpointAdapter.substitutedTypeReference(original.getType(),
+                mappings);
+    }
+
+    @Override
+    public String toString() {
+        return getType().toString();
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/subst/ParameterizedTypeProjection.java b/tools/signature-tools/src/signature/compare/model/subst/ParameterizedTypeProjection.java
new file mode 100644
index 0000000..59836db
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/subst/ParameterizedTypeProjection.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.subst;
+
+import signature.model.IClassReference;
+import signature.model.IParameterizedType;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+import signature.model.impl.SigParameterizedType;
+
+import java.util.List;
+import java.util.Map;
+
+public class ParameterizedTypeProjection implements IParameterizedType {
+
+    private final IParameterizedType original;
+
+    private final Map<ITypeVariableDefinition, ITypeReference> mappings;
+
+    public ParameterizedTypeProjection(IParameterizedType original,
+            Map<ITypeVariableDefinition, ITypeReference> mappings) {
+        this.original = original;
+        this.mappings = mappings;
+    }
+
+    public ITypeReference getOwnerType() {
+        ITypeReference ownerType = original.getOwnerType();
+        if (ownerType == null) {
+            return null;
+        }
+        return ViewpointAdapter.substitutedTypeReference(ownerType, mappings);
+    }
+
+    private IClassReference rawType = null;
+
+    /**
+     * Returns the raw type with substituted type variables.
+     * 
+     * @return the raw type with substituted type variables
+     */
+    public IClassReference getRawType() {
+        if (rawType == null) {
+            rawType = (IClassReference) ViewpointAdapter
+                    .substitutedTypeReference(original.getRawType(),
+                            ViewpointAdapter.createTypeMapping(this, original
+                                    .getRawType().getClassDefinition()));
+        }
+        return rawType;
+    }
+
+    private List<ITypeReference> arguments = null;
+
+    public List<ITypeReference> getTypeArguments() {
+        if (arguments == null) {
+            arguments = ViewpointAdapter.substitutedTypeReferences(original
+                    .getTypeArguments(), mappings);
+        }
+        return arguments;
+    }
+
+    @Override
+    public int hashCode() {
+        return SigParameterizedType.hashCode(this);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return SigParameterizedType.equals(this, obj);
+    }
+
+    @Override
+    public String toString() {
+        return SigParameterizedType.toString(this);
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/subst/ViewpointAdapter.java b/tools/signature-tools/src/signature/compare/model/subst/ViewpointAdapter.java
new file mode 100644
index 0000000..88f457f
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/subst/ViewpointAdapter.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.subst;
+
+import signature.model.IArrayType;
+import signature.model.IClassDefinition;
+import signature.model.IClassReference;
+import signature.model.IParameterizedType;
+import signature.model.IPrimitiveType;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+import signature.model.ITypeVariableReference;
+import signature.model.IWildcardType;
+import signature.model.impl.SigClassReference;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class ViewpointAdapter {
+
+    static Map<ITypeVariableDefinition, ITypeReference> createTypeMapping(
+            IParameterizedType paramameterizedType,
+            IClassDefinition parameterizedTypeDefinition) {
+        List<ITypeVariableDefinition> typeParameters =
+                parameterizedTypeDefinition.getTypeParameters();
+        List<ITypeReference> actualTypeArguments = paramameterizedType
+                .getTypeArguments();
+        if (actualTypeArguments == null || typeParameters == null) {
+            return Collections.emptyMap();
+        }
+        Map<ITypeVariableDefinition, ITypeReference> substitution =
+                new HashMap<ITypeVariableDefinition, ITypeReference>();
+        Iterator<ITypeVariableDefinition> paramsIterator = typeParameters
+                .iterator();
+        Iterator<ITypeReference> argumentsIterator = actualTypeArguments
+                .iterator();
+        while (paramsIterator.hasNext() && argumentsIterator.hasNext()) {
+            substitution.put(paramsIterator.next(), argumentsIterator.next());
+        }
+        return substitution;
+    }
+
+    public static Set<ITypeReference> substitutedTypeReferences(
+            Set<ITypeReference> original,
+            Map<ITypeVariableDefinition, ITypeReference> mappings) {
+        List<ITypeReference> result = new ArrayList<ITypeReference>(original);
+        return new HashSet<ITypeReference>(substitutedTypeReferences(result,
+                mappings));
+    }
+
+    public static List<ITypeReference> substitutedTypeReferences(
+            List<ITypeReference> original,
+            Map<ITypeVariableDefinition, ITypeReference> mappings) {
+        List<ITypeReference> result = new ArrayList<ITypeReference>(original
+                .size());
+        for (ITypeReference typeReference : original) {
+            result.add(substitutedTypeReference(typeReference, mappings));
+        }
+        return result;
+    }
+
+    public static ITypeReference substitutedTypeReference(
+            ITypeReference original,
+            Map<ITypeVariableDefinition, ITypeReference> mappings) {
+        ITypeReference type = original;
+        if (type instanceof IClassReference) {
+            return new ClassReferenceProjection((IClassReference) original,
+                    mappings);
+        } else if (type instanceof IPrimitiveType) {
+            return type;
+        } else if (type instanceof IArrayType) {
+            return new ArrayTypeProjection((IArrayType) type, mappings);
+        } else if (type instanceof IParameterizedType) {
+            return new ParameterizedTypeProjection((IParameterizedType) type,
+                    mappings);
+        } else if (type instanceof IWildcardType) {
+            return new WildcardTypeProjection((IWildcardType) type, mappings);
+        } else if (type instanceof ITypeVariableReference) {
+            // here happens the substitution
+            ITypeReference subst = mappings.get(((ITypeVariableReference) type)
+                    .getTypeVariableDefinition());
+            return subst != null ? subst : type;
+        }
+        throw new IllegalStateException();
+    }
+
+    public static IClassReference getReferenceTo(IClassDefinition definition) {
+        return new SigClassReference(new ClassProjection(definition,
+                new HashMap<ITypeVariableDefinition, ITypeReference>()));
+    }
+}
diff --git a/tools/signature-tools/src/signature/compare/model/subst/WildcardTypeProjection.java b/tools/signature-tools/src/signature/compare/model/subst/WildcardTypeProjection.java
new file mode 100644
index 0000000..a59873c
--- /dev/null
+++ b/tools/signature-tools/src/signature/compare/model/subst/WildcardTypeProjection.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.compare.model.subst;
+
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+import signature.model.IWildcardType;
+import signature.model.impl.SigWildcardType;
+
+import java.util.List;
+import java.util.Map;
+
+public class WildcardTypeProjection implements IWildcardType {
+
+    private final IWildcardType original;
+
+    private final Map<ITypeVariableDefinition, ITypeReference> mappings;
+
+    public WildcardTypeProjection(IWildcardType original,
+            Map<ITypeVariableDefinition, ITypeReference> mappings) {
+        this.original = original;
+        this.mappings = mappings;
+    }
+
+    public ITypeReference getLowerBound() {
+        return ViewpointAdapter.substitutedTypeReference(original
+                .getLowerBound(), mappings);
+    }
+
+    public List<ITypeReference> getUpperBounds() {
+        return ViewpointAdapter.substitutedTypeReferences(original
+                .getUpperBounds(), mappings);
+    }
+
+    @Override
+    public int hashCode() {
+        return SigWildcardType.hashCode(this);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return SigWildcardType.equals(this, obj);
+    }
+
+    @Override
+    public String toString() {
+        return SigWildcardType.toString(this);
+    }
+}
diff --git a/tools/signature-tools/src/signature/converter/Main.java b/tools/signature-tools/src/signature/converter/Main.java
new file mode 100644
index 0000000..f426877
--- /dev/null
+++ b/tools/signature-tools/src/signature/converter/Main.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter;
+
+import signature.UsageException;
+import signature.converter.dex.DexFactory;
+import signature.converter.doclet.DocletFactory;
+import signature.io.IApiLoader;
+import signature.io.IApiExternalizer;
+import signature.io.impl.BinaryApi;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+public class Main {
+    // (doclet | dex) sourcefiles --out file --name name --packages packageName{
+    // packageName}" +
+    public static void main(String[] args) throws IOException {
+        String type = args[0];
+        Set<String> sources = new HashSet<String>();
+        int at = 1;
+        for (/* at */; at < args.length; at++) {
+            if ("--out".equals(args[at])) {
+                break;
+            }
+            sources.add(args[at]);
+        }
+
+        if (!"--out".equals(args[at])) {
+            throw new UsageException();
+        }
+        String targetFile = args[++at];
+
+        if (!"--name".equals(args[++at])) {
+            throw new UsageException();
+        }
+        String name = args[++at];
+
+        if (!"--packages".equals(args[++at])) {
+            throw new UsageException();
+        }
+        Set<String> packages = new HashSet<String>();
+        ++at;
+        for (/* at */; at < args.length; at++) {
+            packages.add(args[at]);
+        }
+
+        IApiExternalizer externalizer = new BinaryApi();
+        IApiLoader factory = null;
+
+        if ("doclet".equals(type)) {
+            factory = new DocletFactory();
+        } else if ("dex".equals(type)) {
+            factory = new DexFactory();
+        } else {
+            throw new UsageException();
+        }
+
+        externalizer.externalizeApi(targetFile, factory.loadApi(name,
+                Visibility.PROTECTED, sources, packages));
+    }
+}
diff --git a/tools/signature-tools/src/signature/converter/Visibility.java b/tools/signature-tools/src/signature/converter/Visibility.java
new file mode 100644
index 0000000..653c617
--- /dev/null
+++ b/tools/signature-tools/src/signature/converter/Visibility.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter;
+
+/**
+ * This enum defines which members are part of the API.
+ * 
+ * <ul>
+ * <li><code>PUBLIC</code> only the public classes and members are included.
+ * <li><code>PROTECTED</code> the public and protected classes members are
+ * included.
+ * <li><code>PACKAGE</code> the public, protected and package visible classes
+ * and members are included.
+ * <li><code>PRIVATE</code> all classes and members are included.
+ * </ul>
+ * <p>
+ * The default visibility mode is <code>PROTECTED</code>.
+ * 
+ */
+public enum Visibility {
+    PUBLIC, PROTECTED, PACKAGE, PRIVATE;
+}
diff --git a/tools/signature-tools/src/signature/converter/dex/DexFactory.java b/tools/signature-tools/src/signature/converter/dex/DexFactory.java
new file mode 100644
index 0000000..b7cc00e
--- /dev/null
+++ b/tools/signature-tools/src/signature/converter/dex/DexFactory.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter.dex;
+
+import dex.structure.DexFile;
+import signature.converter.Visibility;
+import signature.io.IApiLoader;
+import signature.model.IApi;
+import signature.model.IPackage;
+import signature.model.impl.SigApi;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Set;
+
+public class DexFactory implements IApiLoader {
+
+    public IApi loadApi(String name, Visibility visibility,
+            Set<String> fileNames, Set<String> packageNames) throws
+            IOException {
+        DexToSigConverter converter = new DexToSigConverter();
+        Set<DexFile> files = DexUtil.getDexFiles(fileNames);
+        SigApi api = converter.convertApi(name, files, visibility);
+
+        Iterator<IPackage> it = api.getPackages().iterator();
+        while (it.hasNext()) {
+            IPackage aPackage = it.next();
+            boolean found = false;
+            for (String packageName : packageNames) {
+                if (aPackage.getName().equals(packageName)) {
+                    found = true;
+                }
+            }
+            if (!found) {
+                it.remove();
+            }
+        }
+        return api;
+    }
+}
diff --git a/tools/signature-tools/src/signature/converter/dex/DexToSigConverter.java b/tools/signature-tools/src/signature/converter/dex/DexToSigConverter.java
new file mode 100644
index 0000000..13312bd
--- /dev/null
+++ b/tools/signature-tools/src/signature/converter/dex/DexToSigConverter.java
@@ -0,0 +1,938 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter.dex;
+
+import static signature.converter.dex.DexUtil.convertAnyWay;
+import static signature.converter.dex.DexUtil.declaresExceptions;
+import static signature.converter.dex.DexUtil.declaresMemberClasses;
+import static signature.converter.dex.DexUtil.findPackageInfo;
+import static signature.converter.dex.DexUtil.getClassModifiers;
+import static signature.converter.dex.DexUtil.getClassName;
+import static signature.converter.dex.DexUtil.getDefaultMappingsAnnotation;
+import static signature.converter.dex.DexUtil.getDexName;
+import static signature.converter.dex.DexUtil.getEnclosingClassName;
+import static signature.converter.dex.DexUtil.getExceptionSignature;
+import static signature.converter.dex.DexUtil.getGenericSignature;
+import static signature.converter.dex.DexUtil.getKind;
+import static signature.converter.dex.DexUtil.getMemberClassNames;
+import static signature.converter.dex.DexUtil.getModifier;
+import static signature.converter.dex.DexUtil.getPackageName;
+import static signature.converter.dex.DexUtil.getQualifiedName;
+import static signature.converter.dex.DexUtil.hasAnnotationDefaultSignature;
+import static signature.converter.dex.DexUtil.hasGenericSignature;
+import static signature.converter.dex.DexUtil.isAnnotation;
+import static signature.converter.dex.DexUtil.isConstructor;
+import static signature.converter.dex.DexUtil.isEnclosingClass;
+import static signature.converter.dex.DexUtil.isEnum;
+import static signature.converter.dex.DexUtil.isInternalAnnotation;
+import static signature.converter.dex.DexUtil.isJavaLangObject;
+import static signature.converter.dex.DexUtil.isMethod;
+import static signature.converter.dex.DexUtil.isVisible;
+import static signature.converter.dex.DexUtil.splitTypeList;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import signature.converter.Visibility;
+import signature.model.IAnnotation;
+import signature.model.IAnnotationElement;
+import signature.model.IAnnotationField;
+import signature.model.IClassDefinition;
+import signature.model.IClassReference;
+import signature.model.IConstructor;
+import signature.model.IEnumConstant;
+import signature.model.IField;
+import signature.model.IMethod;
+import signature.model.IPackage;
+import signature.model.IParameter;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+import signature.model.Kind;
+import signature.model.Modifier;
+import signature.model.impl.SigAnnotation;
+import signature.model.impl.SigAnnotationElement;
+import signature.model.impl.SigAnnotationField;
+import signature.model.impl.SigApi;
+import signature.model.impl.SigClassDefinition;
+import signature.model.impl.SigClassReference;
+import signature.model.impl.SigConstructor;
+import signature.model.impl.SigEnumConstant;
+import signature.model.impl.SigExecutableMember;
+import signature.model.impl.SigField;
+import signature.model.impl.SigMethod;
+import signature.model.impl.SigPackage;
+import signature.model.impl.SigParameter;
+import signature.model.impl.Uninitialized;
+import signature.model.util.TypePool;
+import dex.structure.DexAnnotation;
+import dex.structure.DexAnnotationAttribute;
+import dex.structure.DexClass;
+import dex.structure.DexEncodedAnnotation;
+import dex.structure.DexEncodedValue;
+import dex.structure.DexField;
+import dex.structure.DexFile;
+import dex.structure.DexMethod;
+import dex.structure.DexParameter;
+
+/**
+ * Converts a set of dex files to the signature compare api.
+ */
+public final class DexToSigConverter implements IClassInitializer {
+
+    private final FieldPool elementPool;
+    private final TypePool factory;
+    private static final Set<IField> EMPTY_FIELDS = Collections.emptySet();
+    private static final Set<IEnumConstant> EMPTY_ENUM_CONSTANTS = Collections
+            .emptySet();
+    private static final Set<IAnnotationField> EMPTY_ANNOTATION_FIELDS =
+            Collections.emptySet();
+    private static final List<ITypeVariableDefinition> EMPTY_TYPE_VARIABLES =
+            Collections.emptyList();
+    private static final Set<IClassDefinition> EMPTY_INNER_CLASSES =
+            Collections.emptySet();
+    private static final Set<ITypeReference> EMPTY_EXCEPTIONS = Collections
+            .emptySet();
+    private Visibility visibility;
+    private Map<String, DexClass> dexNameToDexClass;
+
+
+    /**
+     * Creates a new instance of {@link DexToSigConverter}.
+     */
+    public DexToSigConverter() {
+        factory = new TypePool();
+        elementPool = new FieldPool();
+    }
+
+
+    public SigApi convertApi(String apiName, Set<DexFile> dexFiles,
+            Visibility visibility) {
+        this.visibility = visibility;
+        SigApi api = new SigApi(apiName, visibility);
+        api.setPackages(convertPackages(dexFiles));
+        factory.replaceAllUninitialiezWithNull();
+        return api;
+    }
+
+    /**
+     * Converts the given {@link DexFile}s into the corresponding (packages
+     * including their (classes and their members, etc.))E
+     * 
+     * @param parsedFiles
+     *            the dex files to convert
+     * @return the converted packages
+     */
+    /* package */Set<IPackage> convertPackages(Set<DexFile> parsedFiles) {
+        Map<String, SigPackage> packageNameToPackage =
+                new HashMap<String, SigPackage>();
+        Map<SigPackage, Set<DexClass>> packageToDexClasses =
+                new HashMap<SigPackage, Set<DexClass>>();
+
+        dexNameToDexClass = new HashMap<String, DexClass>();
+
+        for (DexFile dexFile : parsedFiles) {
+            List<DexClass> definedClasses = dexFile.getDefinedClasses();
+            for (DexClass dexClass : definedClasses) {
+
+                dexNameToDexClass.put(dexClass.getName(), dexClass);
+
+                String dexName = dexClass.getName();
+                String packageName = getPackageName(dexName);
+                SigPackage aPackage = packageNameToPackage.get(packageName);
+                if (aPackage == null) {
+                    aPackage = convertPackage(packageName);
+                    packageNameToPackage.put(packageName, aPackage);
+
+                    Set<DexClass> classes = new HashSet<DexClass>();
+                    packageToDexClasses.put(aPackage, classes);
+                }
+                Set<DexClass> classes = packageToDexClasses.get(aPackage);
+                classes.add(dexClass);
+            }
+        }
+
+        Set<SigClassDefinition> allClasses = new HashSet<SigClassDefinition>();
+
+        for (SigPackage aPackage : packageToDexClasses.keySet()) {
+            Set<SigClassDefinition> classes = convertClasses(packageToDexClasses
+                    .get(aPackage));
+            allClasses.addAll(classes);
+            aPackage.setClasses(new HashSet<IClassDefinition>(classes));
+        }
+
+        // remove package info
+        for (SigPackage aPackage : packageToDexClasses.keySet()) {
+            IClassDefinition packageInfo = findPackageInfo(aPackage);
+            if (packageInfo != null) {
+                aPackage.setAnnotations(packageInfo.getAnnotations());
+                aPackage.getClasses().remove(packageInfo);
+            }
+        }
+
+        // link enclosed classes only if they are part of visible api
+        for (SigClassDefinition sigClass : allClasses) {
+            String dexName = getDexName(sigClass);
+            DexClass dexClass = dexNameToDexClass.get(dexName);
+
+            if (declaresMemberClasses(dexClass)) {
+                Set<String> enclosedClassesNames =
+                        getMemberClassNames(dexClass);
+                Set<IClassDefinition> memberClasses =
+                        new HashSet<IClassDefinition>();
+                for (String enclosedClassName : enclosedClassesNames) {
+                    SigClassDefinition memberClass = factory.getClass(
+                            getPackageName(enclosedClassName),
+                            getClassName(enclosedClassName));
+                    // add inner class only if parsed
+                    if (allClasses.contains(memberClass)) {
+                        memberClasses.add(memberClass);
+                    }
+                }
+                sigClass.setInnerClasses(memberClasses);
+            } else {
+                sigClass.setInnerClasses(EMPTY_INNER_CLASSES);
+            }
+        }
+
+        // remove inner classes, is outer class is not visible
+        for (SigClassDefinition sigClass : allClasses) {
+            if (hasInvisibleParent(sigClass, dexNameToDexClass)) {
+                SigPackage sigPackage = packageNameToPackage.get(sigClass
+                        .getPackageName());
+                sigPackage.getClasses().remove(sigClass);
+            }
+        }
+        return new HashSet<IPackage>(packageToDexClasses.keySet());
+    }
+
+    private boolean hasInvisibleParent(IClassDefinition sigClass,
+            Map<String, DexClass> dexNameToDexClass) {
+
+        do {
+            String dexName = getDexName(sigClass);
+            DexClass dexClass = dexNameToDexClass.get(dexName);
+            if (isEnclosingClass(dexClass)) {
+                IClassDefinition declaringClass = sigClass.getDeclaringClass();
+                DexClass declaringDexClass = dexNameToDexClass
+                        .get(getDexName(declaringClass));
+                if (!isVisible(declaringDexClass, visibility)) {
+                    return true;
+                }
+            }
+        } while ((sigClass = sigClass.getDeclaringClass()) != null);
+        return false;
+    }
+
+    /**
+     * Converts a simple string to the corresponding {@link SigPackage}.<br>
+     * Format: "a.b.c"
+     * 
+     * @param packageName
+     *            the name of the package
+     * @return the package
+     */
+    protected SigPackage convertPackage(String packageName) {
+        SigPackage sigPackage = new SigPackage(packageName);
+        return sigPackage;
+    }
+
+    /**
+     * Converts a set of {@link DexClass} objects to a set of the corresponding
+     * {@link SigClassDefinition} objects.
+     * 
+     * @param dexClasses
+     *            the {@link DexClass} objects
+     * @return a set of {@link DexClass} objects
+     */
+    protected Set<SigClassDefinition> convertClasses(Set<DexClass> dexClasses) {
+        Set<SigClassDefinition> classes = new HashSet<SigClassDefinition>();
+        for (DexClass dexClass : dexClasses) {
+            // convert all classes but synthetic, return only initialized
+            if (convertAnyWay(dexClass)) {
+                SigClassDefinition sigCLass = convertClass(dexClass);
+                if (isVisible(dexClass, visibility)) {
+                    classes.add(sigCLass);
+                }
+            }
+        }
+        return classes;
+    }
+
+    /**
+     * Converts a {@link DexClass} to the corresponding
+     * {@link SigClassDefinition}.
+     * 
+     * @param dexClass
+     *            the {@link DexClass} to convert
+     * @return the corresponding {@link SigClassDefinition}
+     */
+    protected SigClassDefinition convertClass(DexClass dexClass) {
+        assert dexClass != null;
+
+        String packageName = getPackageName(dexClass.getName());
+        String className = getClassName(dexClass.getName());
+        SigClassDefinition sigClass = factory.getClass(packageName, className);
+        // Kind
+        sigClass.setKind(getKind(dexClass));
+        // modifiers
+        Set<Modifier> modifiers = getModifier(getClassModifiers(dexClass));
+        sigClass.setModifiers(modifiers);
+
+        if (isEnclosingClass(dexClass)) {
+            String declaringClassDexName = getEnclosingClassName(dexClass);
+            declaringClassDexName = getClassName(declaringClassDexName);
+            // declaring class is in same package
+            sigClass.setDeclaringClass(factory.getClass(sigClass
+                    .getPackageName(), declaringClassDexName));
+        } else {
+            sigClass.setDeclaringClass(null);
+        }
+
+        if (hasGenericSignature(dexClass)) {
+            GenericSignatureParser parser = new GenericSignatureParser(factory,
+                    this);
+            parser.parseForClass(sigClass, getGenericSignature(dexClass));
+            sigClass.setTypeParameters(parser.formalTypeParameters);
+
+            if (Kind.INTERFACE.equals(sigClass.getKind())) {
+                sigClass.setSuperClass(null);
+            } else {
+                sigClass.setSuperClass(parser.superclassType);
+            }
+
+            sigClass.setInterfaces(new HashSet<ITypeReference>(
+                    parser.interfaceTypes));
+        } else {
+
+            // Type parameters
+            sigClass.setTypeParameters(EMPTY_TYPE_VARIABLES);
+
+            // java.lang.Object has no super class
+            if (isJavaLangObject(dexClass)) {
+                sigClass.setSuperClass(null);
+            } else {
+
+                if (Kind.INTERFACE.equals(sigClass.getKind())
+                        || Kind.ANNOTATION.equals(sigClass.getKind())) {
+                    sigClass.setSuperClass(null);
+                } else {
+                    String superClassPackageName = getPackageName(dexClass
+                            .getSuperClass());
+                    String superClassName = getClassName(dexClass
+                            .getSuperClass());
+                    sigClass.setSuperClass(factory.getClassReference(
+                            superClassPackageName, superClassName));
+                }
+            }
+
+            List<String> interfaceDexNames = dexClass.getInterfaces();
+            Set<ITypeReference> interfaces = new HashSet<ITypeReference>();
+            for (String interfaceDexName : interfaceDexNames) {
+                String interfacePackageName = getPackageName(interfaceDexName);
+                String interfaceName = getClassName(interfaceDexName);
+                SigClassDefinition interfaze = factory.getClass(
+                        interfacePackageName, interfaceName);
+                interfaze.setKind(Kind.INTERFACE);
+                interfaces.add(new SigClassReference(interfaze));
+            }
+            sigClass.setInterfaces(interfaces);
+        }
+
+        // constructors
+        Set<SigConstructor> constructors = convertConstructors(dexClass
+                .getMethods());
+        for (SigConstructor constructor : constructors) {
+            constructor.setDeclaringClass(sigClass);
+        }
+        sigClass.setConstructors(new HashSet<IConstructor>(constructors));
+
+        // methods
+        Set<SigMethod> methods = Collections.emptySet();
+
+
+        if (isAnnotation(dexClass)) {
+            Map<String, Object> mappings = getDefaultValueMapping(dexClass);
+            Set<SigAnnotationField> annotationFields = convertAnnotationFields(
+                    dexClass.getMethods(), mappings);
+            sigClass.setAnnotationFields(new HashSet<IAnnotationField>(
+                    annotationFields));
+            addAnnotationsToAnnotationFields(dexClass.getMethods(),
+                    annotationFields);
+
+            sigClass.setEnumConstants(EMPTY_ENUM_CONSTANTS);
+            sigClass.setFields(EMPTY_FIELDS);
+
+            // sigClass.setAnnotationFields(new
+            // HashSet<IAnnotationField>(convertAnnotationFields(dexClass)));
+        } else if (isEnum(dexClass)) {
+            Set<IField> fields = new HashSet<IField>();
+            Set<IEnumConstant> enumConstants = new HashSet<IEnumConstant>();
+
+            for (DexField dexField : dexClass.getFields()) {
+                if (isVisible(dexField, visibility)) {
+                    if (dexField.isEnumConstant()) {
+                        enumConstants.add(convertEnumConstant(dexField));
+                    } else {
+                        fields.add(convertField(dexField));
+                    }
+                }
+            }
+
+            sigClass.setFields(fields);
+            sigClass.setEnumConstants(enumConstants);
+            sigClass.setAnnotationFields(EMPTY_ANNOTATION_FIELDS);
+            methods = convertMethods(dexClass.getMethods());
+        } else {
+            // fields
+            sigClass.setFields(new HashSet<IField>(convertFields(dexClass
+                    .getFields())));
+            sigClass.setEnumConstants(EMPTY_ENUM_CONSTANTS);
+            sigClass.setAnnotationFields(EMPTY_ANNOTATION_FIELDS);
+            methods = convertMethods(dexClass.getMethods());
+        }
+
+        for (SigMethod method : methods) {
+            method.setDeclaringClass(sigClass);
+        }
+        sigClass.setMethods(new HashSet<IMethod>(methods));
+
+        // Annotations
+        sigClass.setAnnotations(convertAnnotations(dexClass.getAnnotations()));
+
+        return sigClass;
+    }
+
+    @SuppressWarnings("unchecked")
+    private Map<String, Object> getDefaultValueMapping(DexClass dexClass) {
+        HashMap<String, Object> mappings = new HashMap<String, Object>();
+        if (hasAnnotationDefaultSignature(dexClass)) {
+            // read mapping to defaults from annotation
+            DexAnnotation annotation = getDefaultMappingsAnnotation(dexClass);
+            DexAnnotationAttribute dexAnnotationAttribute = annotation
+                    .getAttributes().get(0);
+            if ("value".equals(dexAnnotationAttribute.getName())) {
+                DexEncodedValue encodedValue = dexAnnotationAttribute
+                        .getEncodedValue();
+                DexEncodedValue value = (DexEncodedValue) encodedValue
+                        .getValue();
+                List<DexAnnotationAttribute> defaults = 
+                        (List<DexAnnotationAttribute>) value.getValue();
+                for (DexAnnotationAttribute defaultAttribute : defaults) {
+                    mappings.put(defaultAttribute.getName(),
+                            convertEncodedValue(defaultAttribute
+                                    .getEncodedValue()));
+                }
+            }
+        }
+        return mappings;
+    }
+
+
+    private void addAnnotationsToAnnotationFields(List<DexMethod> methods,
+            Set<SigAnnotationField> annotationFields) {
+        Map<String, SigAnnotationField> nameToAnnotationField =
+                new HashMap<String, SigAnnotationField>();
+
+        for (SigAnnotationField annotationField : annotationFields) {
+            nameToAnnotationField.put(annotationField.getName(),
+                    annotationField);
+        }
+
+        for (DexMethod method : methods) {
+            SigAnnotationField annotationField = nameToAnnotationField
+                    .get(method.getName());
+            annotationField.setAnnotations(convertAnnotations(method
+                    .getAnnotations()));
+        }
+    }
+
+
+    private Set<SigAnnotationField> convertAnnotationFields(
+            List<DexMethod> list, Map<String, Object> mappings) {
+        Set<SigAnnotationField> annotationfields =
+                new HashSet<SigAnnotationField>();
+        for (DexMethod dexMethod : list) {
+            if (isVisible(dexMethod, visibility)) {
+                annotationfields.add(convertAnnotationField(dexMethod, mappings
+                        .get(dexMethod.getName())));
+            }
+        }
+        return annotationfields;
+    }
+
+    private SigAnnotationField convertAnnotationField(DexMethod dexMethod,
+            Object defaultValue) {
+        SigAnnotationField annotationField = new SigAnnotationField(dexMethod
+                .getName());
+        annotationField.setDefaultValue(defaultValue);
+        annotationField.setModifiers(getModifier(dexMethod.getModifiers()));
+        GenericSignatureParser parser = new GenericSignatureParser(factory,
+                this);
+        annotationField.setType(parser.parseNonGenericType(dexMethod
+                .getReturnType()));
+        return annotationField;
+    }
+
+    private IEnumConstant convertEnumConstant(DexField dexField) {
+        String qualifiedTypeName = getQualifiedName(dexField
+                .getDeclaringClass().getName());
+        SigEnumConstant enumConstant = elementPool.getEnumConstant(
+                qualifiedTypeName, dexField.getName());
+        Set<Modifier> modifiers = getModifier(dexField.getModifiers());
+        modifiers.add(Modifier.STATIC);
+        enumConstant.setModifiers(modifiers);
+
+        String typePackageName = getPackageName(dexField.getType());
+        String typeName = getClassName(dexField.getType());
+        enumConstant.setType(factory.getClassReference(typePackageName,
+                typeName));
+        enumConstant.setAnnotations(convertAnnotations(dexField
+                .getAnnotations()));
+        return enumConstant;
+    }
+
+    private Set<SigField> convertFields(List<DexField> dexFields) {
+        Set<SigField> fields = new HashSet<SigField>();
+        for (DexField dexField : dexFields) {
+            if (isVisible(dexField, visibility)) {
+                fields.add(convertField(dexField));
+            }
+        }
+        return fields;
+    }
+
+    private SigField convertField(DexField dexField) {
+        String qualTypeName = getQualifiedName(dexField.getDeclaringClass()
+                .getName());
+        SigField field = elementPool.getField(qualTypeName, dexField.getName());
+
+        field.setModifiers(getModifier(dexField.getModifiers()));
+
+        field.setAnnotations(convertAnnotations(dexField.getAnnotations()));
+
+        if (hasGenericSignature(dexField)) {
+            GenericSignatureParser parser = new GenericSignatureParser(factory,
+                    this);
+            String declaringClassPackageName = getPackageName(dexField
+                    .getDeclaringClass().getName());
+            String declaringClassName = getClassName(dexField
+                    .getDeclaringClass().getName());
+
+            parser.parseForField(factory.getClass(declaringClassPackageName,
+                    declaringClassName), getGenericSignature(dexField));
+            field.setType(parser.fieldType);
+        } else {
+            GenericSignatureParser parser = new GenericSignatureParser(factory,
+                    this);
+            field.setType(parser.parseNonGenericType(dexField.getType()));
+        }
+
+        return field;
+    }
+
+    /**
+     * Converts a set of {@link DexMethod} to a set of corresponding
+     * {@link IConstructor}. This method ignores methods which are not
+     * constructors.
+     * 
+     * @param methods
+     *            the {@link DexMethod}s to convert
+     * @return the corresponding {@link IConstructor}s
+     */
+    private Set<SigConstructor> convertConstructors(List<DexMethod> methods) {
+        Set<SigConstructor> constructors = new HashSet<SigConstructor>();
+        for (DexMethod method : methods) {
+            if (isConstructor(method) && isVisible(method, visibility)) {
+                constructors.add(convertConstructor(method));
+            }
+        }
+        return constructors;
+    }
+
+    /**
+     * Converts a set of {@link DexMethod} to a set of corresponding
+     * {@link DexMethod}. This method ignores methods which are constructors.
+     * 
+     * @param methods
+     *            the {@link DexMethod}s to convert
+     * @return the corresponding {@link IConstructor}s
+     */
+    private Set<SigMethod> convertMethods(List<DexMethod> methods) {
+        Set<SigMethod> sigMethods = new HashSet<SigMethod>();
+        for (DexMethod method : methods) {
+            if (isMethod(method) && isVisible(method, visibility)) {
+                sigMethods.add(convertMethod(method));
+            }
+        }
+        return sigMethods;
+    }
+
+    /**
+     * Converts a dexMethod which must be a constructor to the corresponding
+     * {@link SigConstructor} instance.
+     * 
+     * @param dexMethod
+     *            the dex constructor to convert
+     * @return the corresponding {@link SigConstructor}
+     */
+    public SigConstructor convertConstructor(DexMethod dexMethod) {
+        String declaringClassName = getClassName(dexMethod.getDeclaringClass()
+                .getName());
+
+        SigConstructor constructor = new SigConstructor(declaringClassName);
+        constructor.setModifiers(getModifier(dexMethod.getModifiers()));
+        String declaringClassPackageName = getPackageName(dexMethod
+                .getDeclaringClass().getName());
+
+
+        SigClassDefinition declaringClass = factory.getClass(
+                declaringClassPackageName, declaringClassName);
+        constructor.setDeclaringClass(declaringClass);
+
+        // Annotations
+        constructor.setAnnotations(convertAnnotations(dexMethod
+                .getAnnotations()));
+
+        if (hasGenericSignature(dexMethod)) {
+            GenericSignatureParser parser = new GenericSignatureParser(factory,
+                    this);
+            parser.parseForConstructor(constructor,
+                    getGenericSignature(dexMethod));
+
+            // type parameters
+            constructor.setTypeParameters(parser.formalTypeParameters);
+
+            // parameters
+            // generic parameter types parameters
+            List<DexParameter> dexParameters = dexMethod.getParameters();
+            List<IParameter> parameters = new ArrayList<IParameter>(
+                    parser.parameterTypes.size());
+            Iterator<DexParameter> iterator = dexParameters.iterator();
+            for (ITypeReference parameterType : parser.parameterTypes) {
+                SigParameter parameter = new SigParameter(parameterType);
+                iterator.hasNext();
+                DexParameter dexParam = iterator.next();
+                parameter.setAnnotations(convertAnnotations(dexParam
+                        .getAnnotations()));
+                parameters.add(parameter);
+            }
+
+            constructor.setParameters(parameters);
+
+            // exceptions
+            constructor.setExceptions(new HashSet<ITypeReference>(
+                    parser.exceptionTypes));
+
+        } else {
+            convertNonGenericExecutableMember(constructor, dexMethod);
+
+            // remove first parameter of non static inner class constructors
+            // implicit outer.this reference
+            if (declaringClass.getDeclaringClass() != null) {
+                if (!declaringClass.getModifiers().contains(Modifier.STATIC)) {
+                    if (constructor.getParameters().isEmpty()) {
+                        throw new IllegalStateException(
+                                "Expected at least one parameter!");
+                    }
+                    IParameter first = constructor.getParameters().remove(0);
+                    String enclosingName = declaringClass.getDeclaringClass()
+                            .getName();
+                    String firstParameterTypeName = ((IClassReference) first
+                            .getType()).getClassDefinition().getName();
+                    if (!enclosingName.equals(firstParameterTypeName))
+                        throw new IllegalStateException(
+                                "Expected first constructor parameter of type "
+                                        + enclosingName);
+                }
+            }
+        }
+
+        addExceptions(constructor, dexMethod);
+        return constructor;
+    }
+
+    public SigMethod convertMethod(DexMethod dexMethod) {
+        SigMethod method = new SigMethod(dexMethod.getName());
+        method.setModifiers(getModifier(dexMethod.getModifiers()));
+
+        String declaringClassPackageName = getPackageName(dexMethod
+                .getDeclaringClass().getName());
+        String declaringClassName = getClassName(dexMethod.getDeclaringClass()
+                .getName());
+
+        method.setDeclaringClass(factory.getClass(declaringClassPackageName,
+                declaringClassName));
+
+        // Annotations
+        method.setAnnotations(convertAnnotations(dexMethod.getAnnotations()));
+
+        if (hasGenericSignature(dexMethod)) {
+            GenericSignatureParser parser = new GenericSignatureParser(factory,
+                    this);
+            parser.parseForMethod(method, getGenericSignature(dexMethod));
+
+            // type parameters
+            method.setTypeParameters(parser.formalTypeParameters);
+
+            // generic parameter types parameters
+            List<DexParameter> dexParameters = dexMethod.getParameters();
+            List<IParameter> parameters = new ArrayList<IParameter>(
+                    parser.parameterTypes.size());
+            Iterator<DexParameter> iterator = dexParameters.iterator();
+            for (ITypeReference parameterType : parser.parameterTypes) {
+                SigParameter parameter = new SigParameter(parameterType);
+                iterator.hasNext();
+                DexParameter dexParam = iterator.next();
+                parameter.setAnnotations(convertAnnotations(dexParam
+                        .getAnnotations()));
+                parameters.add(parameter);
+            }
+            method.setParameters(parameters);
+
+            // exceptions
+            method.setExceptions(new HashSet<ITypeReference>(
+                    parser.exceptionTypes));
+            method.setReturnType(parser.returnType);
+
+        } else {
+            convertNonGenericExecutableMember(method, dexMethod);
+            GenericSignatureParser parser = new GenericSignatureParser(factory,
+                    this);
+            ITypeReference type = parser.parseNonGenericReturnType(dexMethod
+                    .getReturnType());
+            method.setReturnType(type);
+        }
+        addExceptions(method, dexMethod);
+        return method;
+    }
+
+    private void addExceptions(SigExecutableMember member,
+            DexMethod dexMethod) {
+        if (declaresExceptions(dexMethod)) {
+            String exceptionSignature = getExceptionSignature(dexMethod);
+            Set<String> exceptionTypeNames = splitTypeList(exceptionSignature);
+            Set<ITypeReference> exceptions = new HashSet<ITypeReference>();
+
+            for (String exTypeName : exceptionTypeNames) {
+                String packageName = getPackageName(exTypeName);
+                String className = getClassName(exTypeName);
+                exceptions.add(factory
+                        .getClassReference(packageName, className));
+            }
+            member.setExceptions(exceptions);
+        } else {
+            member.setExceptions(EMPTY_EXCEPTIONS);
+        }
+    }
+
+    private void convertNonGenericExecutableMember(SigExecutableMember member,
+            DexMethod dexMethod) {
+        List<DexParameter> dexParameters = dexMethod.getParameters();
+        List<IParameter> parameters = new ArrayList<IParameter>(dexParameters
+                .size());
+
+        for (DexParameter dexParameter : dexParameters) {
+            GenericSignatureParser parser = new GenericSignatureParser(factory,
+                    this);
+            ITypeReference type = parser.parseNonGenericType(dexParameter
+                    .getTypeName());
+            SigParameter parameter = new SigParameter(type);
+            parameters.add(parameter);
+            // Annotations
+            parameter.setAnnotations(convertAnnotations(dexParameter
+                    .getAnnotations()));
+        }
+        member.setParameters(parameters);
+
+        member.setTypeParameters(EMPTY_TYPE_VARIABLES);
+
+        // if (declaresExceptions(dexMethod)) {
+        // String exceptionSignature = getExceptionSignature(dexMethod);
+        // Set<String> exceptionTypeNames = splitTypeList(exceptionSignature);
+        // Set<IType> exceptions = new HashSet<IType>();
+        //
+        // for (String exTypeName : exceptionTypeNames) {
+        // String packageName = getPackageName(exTypeName);
+        // String className = getClassName(exTypeName);
+        // exceptions.add(factory.getClass(packageName, className));
+        // }
+        // member.setExceptions(exceptions);
+        // } else {
+        // member.setExceptions(EMPTY_EXCEPTIONS);
+        // }
+    }
+
+    /**
+     * Converts a set of {@link DexAnnotation} to a set of corresponding
+     * {@link SigAnnotation}.
+     * 
+     * @param dexAnnotations
+     *            the {@link DexAnnotation}s to convert
+     * @return the corresponding {@link SigAnnotation}s
+     */
+    private Set<IAnnotation> convertAnnotations(
+            Set<DexAnnotation> dexAnnotations) {
+        Set<IAnnotation> annotations = new HashSet<IAnnotation>();
+        for (DexAnnotation dexAnnotation : dexAnnotations) {
+            if (!isInternalAnnotation(dexAnnotation)) {
+                annotations.add(convertAnnotation(dexAnnotation));
+            }
+        }
+        return annotations;
+    }
+
+    /**
+     * Converts a {@link DexAnnotation} to the corresponding
+     * {@link SigAnnotation}.
+     * 
+     * @param dexAnnotation
+     *            the {@link DexAnnotation} to convert
+     * @return the corresponding {@link SigAnnotation}
+     */
+    protected SigAnnotation convertAnnotation(DexAnnotation dexAnnotation) {
+        SigAnnotation sigAnnotation = new SigAnnotation();
+        String packageName = getPackageName(dexAnnotation.getTypeName());
+        String className = getClassName(dexAnnotation.getTypeName());
+        sigAnnotation
+                .setType(factory.getClassReference(packageName, className));
+        sigAnnotation.setElements(convertAnnotationElements(dexAnnotation
+                .getAttributes()));
+        return sigAnnotation;
+    }
+
+    private Set<IAnnotationElement> convertAnnotationElements(
+            List<DexAnnotationAttribute> attributes) {
+        Set<IAnnotationElement> annotationAttributes =
+                new HashSet<IAnnotationElement>();
+        for (DexAnnotationAttribute dexAnnotationAttribute : attributes) {
+            annotationAttributes
+                    .add(convertAnnotationAttribute(dexAnnotationAttribute));
+        }
+        return annotationAttributes;
+    }
+
+    private IAnnotationElement convertAnnotationAttribute(
+            DexAnnotationAttribute dexAnnotationAttribute) {
+
+        SigAnnotationElement sigElement = new SigAnnotationElement();
+        String nameOfField = dexAnnotationAttribute.getName();
+
+
+        String typeName = dexAnnotationAttribute.getAnnotation().getTypeName();
+        SigClassDefinition annotationClass = factory.getClass(
+                getPackageName(typeName), getClassName(typeName));
+        if (!Uninitialized.isInitialized(
+                annotationClass.getAnnotationFields())) {
+            initializeClass(getPackageName(typeName), getClassName(typeName));
+        }
+        for (IAnnotationField field : annotationClass.getAnnotationFields()) {
+            if (nameOfField.equals(field.getName())) {
+                sigElement.setDeclaringField(field);
+            }
+        }
+
+        sigElement.setValue(convertEncodedValue(dexAnnotationAttribute
+                .getEncodedValue()));
+        return sigElement;
+    }
+
+    @SuppressWarnings("unchecked")
+    private Object convertEncodedValue(DexEncodedValue dexEnodedValue) {
+        Object value = null;
+        switch (dexEnodedValue.getType()) {
+        case VALUE_INT:
+        case VALUE_BOOLEAN:
+        case VALUE_BYTE:
+        case VALUE_CHAR:
+        case VALUE_DOUBLE:
+        case VALUE_FLOAT:
+        case VALUE_LONG:
+        case VALUE_NULL:
+        case VALUE_STRING:
+        case VALUE_SHORT:
+            value = dexEnodedValue.getValue();
+            break;
+        case VALUE_ARRAY: {
+            List<DexEncodedValue> dexValues =
+                    (List<DexEncodedValue>) dexEnodedValue.getValue();
+            Object[] arrayValues = new Object[dexValues.size()];
+            int i = 0;
+            for (DexEncodedValue dexValue : dexValues) {
+                arrayValues[i++] = convertEncodedValue(dexValue);
+            }
+            value = arrayValues;
+            break;
+        }
+        case VALUE_ANNOTATION: {
+            DexEncodedAnnotation annotation =
+                    (DexEncodedAnnotation) dexEnodedValue.getValue();
+            SigAnnotation sigAnnotation = new SigAnnotation();
+            String packageName = getPackageName(annotation.getTypeName());
+            String className = getClassName(annotation.getTypeName());
+            sigAnnotation.setType(factory.getClassReference(packageName,
+                    className));
+
+            sigAnnotation.setElements(convertAnnotationElements(annotation
+                    .getValue()));
+            value = sigAnnotation;
+            break;
+        }
+        case VALUE_FIELD: {
+            String fieldDesc = (String) dexEnodedValue.getValue();
+            // FORMAT La/b/E;!CONSTANT
+            String[] typeAndFieldName = fieldDesc.split("!");
+            String typeName = typeAndFieldName[0];
+            String fieldName = typeAndFieldName[1];
+            value = elementPool.getField(getQualifiedName(typeName), fieldName);
+            break;
+        }
+        case VALUE_ENUM: {
+            String fieldDesc = (String) dexEnodedValue.getValue();
+            // FORMAT La/b/E;!CONSTANT
+            String[] typeAndFieldName = fieldDesc.split("!");
+            String typeName = typeAndFieldName[0];
+            String fieldName = typeAndFieldName[1];
+            value = elementPool.getEnumConstant(getQualifiedName(typeName),
+                    fieldName);
+            break;
+        }
+        case VALUE_TYPE: {
+            String typeName = (String) dexEnodedValue.getValue();
+            GenericSignatureParser parser = new GenericSignatureParser(factory,
+                    this);
+            value = parser.parseNonGenericReturnType(typeName);
+            break;
+        }
+        default:
+            throw new IllegalStateException();
+        }
+        return value;
+    }
+
+    public IClassDefinition initializeClass(String packageName,
+            String className) {
+        String dexName = getDexName(packageName, className);
+        DexClass dexClass = dexNameToDexClass.get(dexName);
+        return convertClass(dexClass);
+    }
+}
diff --git a/tools/signature-tools/src/signature/converter/dex/DexUtil.java b/tools/signature-tools/src/signature/converter/dex/DexUtil.java
new file mode 100644
index 0000000..f661af2
--- /dev/null
+++ b/tools/signature-tools/src/signature/converter/dex/DexUtil.java
@@ -0,0 +1,600 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter.dex;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import signature.converter.Visibility;
+import signature.model.IClassDefinition;
+import signature.model.Kind;
+import signature.model.Modifier;
+import signature.model.impl.SigPackage;
+import signature.model.util.ModelUtil;
+import dex.reader.DexBuffer;
+import dex.reader.DexFileReader;
+import dex.structure.DexAnnotatedElement;
+import dex.structure.DexAnnotation;
+import dex.structure.DexAnnotationAttribute;
+import dex.structure.DexClass;
+import dex.structure.DexEncodedValue;
+import dex.structure.DexField;
+import dex.structure.DexFile;
+import dex.structure.DexMethod;
+
+
+public class DexUtil {
+
+    private static final String PACKAGE_INFO = "package-info";
+    private static final String THROWS_ANNOTATION =
+            "Ldalvik/annotation/Throws;";
+    private static final String SIGNATURE_ANNOTATION =
+            "Ldalvik/annotation/Signature;";
+    private static final String ANNOTATION_DEFAULT_ANNOTATION =
+            "Ldalvik/annotation/AnnotationDefault;";
+    private static final String ENCLOSING_CLASS_ANNOTATION =
+            "Ldalvik/annotation/EnclosingClass;";
+    private static final String ENCLOSING_METHOD_ANNOTATION =
+            "Ldalvik/annotation/EnclosingMethod;";
+    private static final String INNER_CLASS_ANNOTATION =
+            "Ldalvik/annotation/InnerClass;";
+    private static final String MEMBER_CLASS_ANNOTATION =
+            "Ldalvik/annotation/MemberClasses;";
+    private static final String JAVA_LANG_OBJECT = "Ljava/lang/Object;";
+
+    private static final Set<String> INTERNAL_ANNOTATION_NAMES;
+
+    static {
+        Set<String> tmp = new HashSet<String>();
+        tmp.add(THROWS_ANNOTATION);
+        tmp.add(SIGNATURE_ANNOTATION);
+        tmp.add(ANNOTATION_DEFAULT_ANNOTATION);
+        tmp.add(ENCLOSING_CLASS_ANNOTATION);
+        tmp.add(ENCLOSING_METHOD_ANNOTATION);
+        tmp.add(INNER_CLASS_ANNOTATION);
+        tmp.add(MEMBER_CLASS_ANNOTATION);
+        INTERNAL_ANNOTATION_NAMES = Collections.unmodifiableSet(tmp);
+    }
+
+    private DexUtil() {
+        // not constructable from outside
+    }
+
+    /**
+     * "La/b/c/A;" -> "a.b.c" "LA;" -> "" empty string
+     * 
+     * @param classIdentifier
+     * @return the package name
+     */
+    public static String getPackageName(String classIdentifier) {
+        String name = removeTrailingSemicolon(removeHeadingL(classIdentifier));
+        return ModelUtil.getPackageName(name.replace("/", "."));
+    }
+
+    /**
+     * "La/b/c/A;" -> "A" "LA;" -> "A"
+     * 
+     * @param classIdentifier
+     *            the dalvik internal identifier
+     * @return the class name
+     */
+    public static String getClassName(String classIdentifier) {
+        String name = removeTrailingSemicolon(removeHeadingL(classIdentifier));
+        return ModelUtil.getClassName(name.replace("/", ".")).replace('$', '.');
+    }
+
+    public static String getQualifiedName(String classIdentifier) {
+        String name = removeTrailingSemicolon(removeHeadingL(classIdentifier));
+        return name.replace('/', '.');
+    }
+
+    private static String removeHeadingL(String className) {
+        assert className.startsWith("L");
+        return className.substring(1);
+    }
+
+    private static String removeTrailingSemicolon(String className) {
+        assert className.endsWith(";");
+        return className.substring(0, className.length() - 1);
+    }
+
+    public static String getDexName(String packageName, String className) {
+        return "L" + packageName.replace('.', '/') + "/"
+                + className.replace('.', '$') + ";";
+    }
+
+    public static String getDexName(IClassDefinition sigClass) {
+        return getDexName(sigClass.getPackageName(), sigClass.getName());
+    }
+
+    /**
+     * Returns correct modifiers for inner classes
+     */
+    public static int getClassModifiers(DexClass clazz) {
+        int modifiers = 0;
+        if (isInnerClass(clazz)) {
+            Integer accessFlags = (Integer) getAnnotationAttributeValue(
+                    getAnnotation(clazz, INNER_CLASS_ANNOTATION),
+                            "accessFlags");
+            modifiers = accessFlags.intValue();
+        } else {
+            modifiers = clazz.getModifiers();
+        }
+        return modifiers;
+    }
+
+    /**
+     * Returns a set containing all modifiers for the given int.
+     * 
+     * @param mod
+     *            the original bit coded modifiers as specified by
+     *            {@link java.lang.reflect.Modifier}
+     * @return a set containing {@link signature.model.Modifier} elements
+     */
+    public static Set<Modifier> getModifier(int mod) {
+        Set<Modifier> modifiers = EnumSet.noneOf(Modifier.class);
+        if (java.lang.reflect.Modifier.isAbstract(mod))
+            modifiers.add(Modifier.ABSTRACT);
+        if (java.lang.reflect.Modifier.isFinal(mod))
+            modifiers.add(Modifier.FINAL);
+        // if (java.lang.reflect.Modifier.isNative(mod))
+        // modifiers.add(Modifier.NATIVE);
+        if (java.lang.reflect.Modifier.isPrivate(mod))
+            modifiers.add(Modifier.PRIVATE);
+        if (java.lang.reflect.Modifier.isProtected(mod))
+            modifiers.add(Modifier.PROTECTED);
+        if (java.lang.reflect.Modifier.isPublic(mod))
+            modifiers.add(Modifier.PUBLIC);
+        if (java.lang.reflect.Modifier.isStatic(mod))
+            modifiers.add(Modifier.STATIC);
+        // if (java.lang.reflect.Modifier.isStrict(mod))
+        // modifiers.add(Modifier.STRICT);
+        // if (java.lang.reflect.Modifier.isSynchronized(mod))
+        // modifiers.add(Modifier.SYNCHRONIZED);
+        // if (java.lang.reflect.Modifier.isTransient(mod))
+        // modifiers.add(Modifier.TRANSIENT);
+        if (java.lang.reflect.Modifier.isVolatile(mod))
+            modifiers.add(Modifier.VOLATILE);
+
+        return modifiers;
+    }
+
+    /**
+     * Returns true if the given class is an enumeration, false otherwise.
+     * 
+     * @param dexClass
+     *            the DexClass under test
+     * @return true if the given class is an enumeration, false otherwise
+     */
+    public static boolean isEnum(DexClass dexClass) {
+        return (getClassModifiers(dexClass) & 0x4000) > 0;
+    }
+
+    /**
+     * Returns true if the given class is an interface, false otherwise.
+     * 
+     * @param dexClass
+     *            the DexClass under test
+     * @return true if the given class is an interface, false otherwise
+     */
+    public static boolean isInterface(DexClass dexClass) {
+        int modifiers = getClassModifiers(dexClass);
+        return java.lang.reflect.Modifier.isInterface(modifiers);
+    }
+
+    /**
+     * Returns true if the given class is an annotation, false otherwise.
+     * 
+     * @param dexClass
+     *            the DexClass under test
+     * @return true if the given class is an annotation, false otherwise
+     */
+    public static boolean isAnnotation(DexClass dexClass) {
+        return (getClassModifiers(dexClass) & 0x2000) > 0;
+    }
+
+    public static boolean isSynthetic(int modifier) {
+        return (modifier & 0x1000) > 0;
+    }
+
+    /**
+     * Returns the Kind of the given DexClass.
+     * 
+     * @param dexClass
+     *            the DexClass under test
+     * @return the Kind of the given class
+     */
+    public static Kind getKind(DexClass dexClass) {
+        // order of branches is crucial since a annotation is also an interface
+        if (isEnum(dexClass)) {
+            return Kind.ENUM;
+        } else if (isAnnotation(dexClass)) {
+            return Kind.ANNOTATION;
+        } else if (isInterface(dexClass)) {
+            return Kind.INTERFACE;
+        } else {
+            return Kind.CLASS;
+        }
+    }
+
+    /**
+     * Returns whether the specified annotated element has an annotation with
+     * type "Ldalvik/annotation/Throws;".
+     * 
+     * @param annotatedElement
+     *            the annotated element to check
+     * @return <code>true</code> if the given annotated element has the
+     *         mentioned annotation, false otherwise
+     */
+    public static boolean declaresExceptions(
+            DexAnnotatedElement annotatedElement) {
+        return getAnnotation(annotatedElement, THROWS_ANNOTATION) != null;
+    }
+
+    /**
+     * Returns the throws signature if the given element has such an annotation,
+     * null otherwise.
+     * 
+     * @param annotatedElement
+     *            the annotated element
+     * @return he generic signature if the given element has such an annotation,
+     *         null otherwise
+     */
+    @SuppressWarnings("unchecked")
+    public static String getExceptionSignature(
+            DexAnnotatedElement annotatedElement) {
+        DexAnnotation annotation = getAnnotation(annotatedElement,
+                THROWS_ANNOTATION);
+        if (annotation != null) {
+            List<DexEncodedValue> value =
+                    (List<DexEncodedValue>) getAnnotationAttributeValue(
+                            annotation, "value");
+            return concatEncodedValues(value);
+        }
+        return null;
+    }
+
+    /**
+     * Splits a list of types:
+     * "Ljava/io/IOException;Ljava/lang/IllegalStateException;" <br>
+     * into separate type designators: <br>
+     * "Ljava/io/IOException;" , "Ljava/lang/IllegalStateException;"
+     * 
+     * @param typeList
+     *            the type list
+     * @return a set of type designators
+     */
+    public static Set<String> splitTypeList(String typeList) {
+        String[] split = typeList.split(";");
+        Set<String> separateTypes = new HashSet<String>();
+        for (String string : split) {
+            separateTypes.add(string + ";");// add semicolon again
+        }
+        return separateTypes;
+    }
+
+    /**
+     * Returns whether the specified annotated element has an annotation with
+     * type "Ldalvik/annotation/Signature;".
+     * 
+     * @param annotatedElement
+     *            the annotated element to check
+     * @return <code>true</code> if the given annotated element has the
+     *         mentioned annotation, false otherwise
+     */
+    public static boolean hasGenericSignature(
+            DexAnnotatedElement annotatedElement) {
+        return getAnnotation(annotatedElement, SIGNATURE_ANNOTATION) != null;
+    }
+
+    /**
+     * Returns the generic signature if the given element has such an
+     * annotation, null otherwise.
+     * 
+     * @param annotatedElement
+     *            the annotated element
+     * @return he generic signature if the given element has such an annotation,
+     *         null otherwise
+     */
+    @SuppressWarnings("unchecked")
+    public static String getGenericSignature(
+            DexAnnotatedElement annotatedElement) {
+        DexAnnotation annotation = getAnnotation(annotatedElement,
+                SIGNATURE_ANNOTATION);
+        if (annotation != null) {
+            List<DexEncodedValue> value =
+                    (List<DexEncodedValue>) getAnnotationAttributeValue(
+                            annotation, "value");
+            return concatEncodedValues(value);
+        }
+        return null;
+    }
+
+    /**
+     * Returns whether the specified annotated element has an annotation with
+     * type "Ldalvik/annotation/AnnotationDefault;".
+     * 
+     * @param annotatedElement
+     *            the annotated element to check
+     * @return <code>true</code> if the given annotated element has the
+     *         mentioned annotation, false otherwise
+     */
+    public static boolean hasAnnotationDefaultSignature(
+            DexAnnotatedElement annotatedElement) {
+        return getAnnotation(
+                annotatedElement, ANNOTATION_DEFAULT_ANNOTATION)!= null;
+    }
+
+    /**
+     * Returns a mapping form annotation attribute name to its default value.
+     * 
+     * @param dexClass
+     *            the class defining a annotation
+     * @return a mapping form annotation attribute name to its default value
+     */
+    public static DexAnnotation getDefaultMappingsAnnotation(
+            DexClass dexClass) {
+        return getAnnotation(dexClass, ANNOTATION_DEFAULT_ANNOTATION);
+    }
+
+    /**
+     * Returns the annotation with the specified type from the given element or
+     * null if no such annotation is available.
+     * 
+     * @param element
+     *            the annotated element
+     * @param annotationType
+     *            the dex internal name of the annotation type
+     * @return the annotation with the specified type or null if not present
+     */
+    public static DexAnnotation getAnnotation(DexAnnotatedElement element,
+            String annotationType) {
+        assert element != null;
+        assert annotationType != null;
+
+        for (DexAnnotation anno : element.getAnnotations()) {
+            if (annotationType.equals(anno.getTypeName())) {
+                return anno;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the value for the specified attribute name of the given
+     * annotation or null if not present.
+     * 
+     * @param annotation
+     *            the annotation
+     * @param attributeName
+     *            the name of the attribute
+     * @return the value for the specified attribute
+     */
+    public static Object getAnnotationAttributeValue(DexAnnotation annotation,
+            String attributeName) {
+        for (DexAnnotationAttribute dexAnnotationAttribute : annotation
+                .getAttributes()) {
+            if (attributeName.equals(dexAnnotationAttribute.getName())) {
+                return dexAnnotationAttribute.getEncodedValue().getValue();
+            }
+        }
+        return null;
+    }
+
+    private static String concatEncodedValues(List<DexEncodedValue> values) {
+        StringBuilder builder = new StringBuilder();
+        for (DexEncodedValue string : values) {
+            builder.append(string.getValue());
+        }
+        return builder.toString();
+    }
+
+    /**
+     * Returns true if the given method is a constructor, false otherwise.
+     * 
+     * @param method
+     *            the method to test
+     * @return true if the given method is a constructor, false otherwise
+     */
+    public static boolean isConstructor(DexMethod method) {
+        return "<init>".equals(method.getName());
+    }
+
+    /**
+     * Returns true if the given method is a static constructor, false
+     * otherwise.
+     * 
+     * @param method
+     *            the method to test
+     * @return true if the given method is a static constructor, false otherwise
+     */
+    public static boolean isStaticConstructor(DexMethod method) {
+        return "<clinit>".equals(method.getName());
+    }
+
+    public static boolean isMethod(DexMethod method) {
+        return !isConstructor(method) && !isStaticConstructor(method);
+    }
+
+    /**
+     * Returns the package-info class for the given package.
+     * 
+     * @param aPackage
+     *            the package
+     * @return the class called "package-info" or null, if not available
+     */
+    public static IClassDefinition findPackageInfo(SigPackage aPackage) {
+        for (IClassDefinition clazz : aPackage.getClasses()) {
+            if (PACKAGE_INFO.equals(clazz.getName())) {
+                return clazz;
+            }
+        }
+        return null;
+    }
+
+    public static boolean isPackageInfo(DexClass clazz) {
+        return PACKAGE_INFO.equals(getClassName(clazz.getName()));
+    }
+
+    public static boolean isInternalAnnotation(DexAnnotation dexAnnotation) {
+        return INTERNAL_ANNOTATION_NAMES.contains(dexAnnotation.getTypeName());
+    }
+
+    /**
+     * An InnerClass annotation is attached to each class which is defined in
+     * the lexical scope of another class's definition. Any class which has this
+     * annotation must also have either an EnclosingClass annotation or an
+     * EnclosingMethod annotation.
+     */
+    public static boolean isInnerClass(DexClass clazz) {
+        return getAnnotation(clazz, INNER_CLASS_ANNOTATION) != null;
+    }
+
+    /**
+     * An EnclosingClass annotation is attached to each class which is either
+     * defined as a member of another class, per se, or is anonymous but not
+     * defined within a method body (e.g., a synthetic inner class). Every class
+     * that has this annotation must also have an InnerClass annotation.
+     * Additionally, a class may not have both an EnclosingClass and an
+     * EnclosingMethod annotation.
+     */
+    public static boolean isEnclosingClass(DexClass clazz) {
+        return getAnnotation(clazz, ENCLOSING_CLASS_ANNOTATION) != null;
+    }
+
+    public static boolean declaresMemberClasses(DexClass dexClass) {
+        return getAnnotation(dexClass, MEMBER_CLASS_ANNOTATION) != null;
+    }
+
+    @SuppressWarnings("unchecked")
+    public static Set<String> getMemberClassNames(DexClass dexClass) {
+        DexAnnotation annotation = getAnnotation(dexClass,
+                MEMBER_CLASS_ANNOTATION);
+        List<DexEncodedValue> enclosedClasses =
+                (List<DexEncodedValue>) getAnnotationAttributeValue(
+                        annotation, "value");
+        Set<String> enclosedClassesNames = new HashSet<String>();
+        for (DexEncodedValue string : enclosedClasses) {
+            enclosedClassesNames.add((String) string.getValue());
+        }
+        return enclosedClassesNames;
+    }
+
+
+    public static String getEnclosingClassName(DexClass dexClass) {
+        DexAnnotation annotation = getAnnotation(dexClass,
+                ENCLOSING_CLASS_ANNOTATION);
+        String value = (String) getAnnotationAttributeValue(annotation,
+                "value");
+        return value;
+    }
+
+    public static boolean convertAnyWay(DexClass dexClass) {
+        return !isSynthetic(getClassModifiers(dexClass))
+                && !isAnonymousClassName(dexClass.getName())
+                || isPackageInfo(dexClass);
+    }
+
+    public static boolean isVisible(DexClass dexClass, Visibility visibility) {
+        // package info is always visible
+        if (isPackageInfo(dexClass)) {
+            return true;
+        }
+
+        if (isDeclaredInMethod(dexClass)) {
+            return false;
+        }
+
+        if (isAnonymousClassName(dexClass.getName())) {
+            return false;
+        }
+
+        int modifiers = getClassModifiers(dexClass);
+
+        return isVisible(modifiers, visibility);
+    }
+
+    private static boolean isDeclaredInMethod(DexClass dexClass) {
+        return getAnnotation(dexClass, ENCLOSING_METHOD_ANNOTATION) != null;
+    }
+
+    /**
+     * Returns whether the given dex identifier is an anonymous class name.
+     * Format: La/b/C$1;
+     * 
+     * @param dexName
+     *            the name to analyze
+     * @return whether the given dex identifier is an anonymous class name
+     */
+    public static boolean isAnonymousClassName(String dexName) {
+        int index = dexName.lastIndexOf('$');
+        return (index != 0) ? Character.isDigit(dexName.charAt(index + 1))
+                : false;
+    }
+
+    public static boolean isVisible(DexField dexField, Visibility visibility) {
+        return isVisible(dexField.getModifiers(), visibility);
+    }
+
+    public static boolean isVisible(DexMethod dexMethod,
+            Visibility visibility) {
+        return isVisible(dexMethod.getModifiers(), visibility);
+    }
+
+    private static boolean isVisible(int modifiers, Visibility visibility) {
+
+        if (isSynthetic(modifiers)) {
+            return false;
+        }
+
+        Set<Modifier> elementModifiers = getModifier(modifiers);
+        if (elementModifiers.contains(Modifier.PUBLIC)) {
+            return true;
+        } else if (elementModifiers.contains(Modifier.PROTECTED)) {
+            return visibility == Visibility.PROTECTED
+                    || visibility == Visibility.PACKAGE
+                    || visibility == Visibility.PRIVATE;
+        } else if (elementModifiers.contains(Modifier.PRIVATE)) {
+            return visibility == Visibility.PRIVATE;
+        } else {
+            return visibility == Visibility.PACKAGE
+                    || visibility == Visibility.PRIVATE;
+        }
+    }
+
+    public static Set<DexFile> getDexFiles(Set<String> fileNames)
+            throws IOException {
+        Set<DexFile> parsedFiles = new HashSet<DexFile>();
+
+        for (String dexFile : fileNames) {
+            DexFileReader reader = new DexFileReader();
+            DexBuffer dexBuffer = new DexBuffer(dexFile);
+            parsedFiles.add(reader.read(dexBuffer));
+        }
+        return parsedFiles;
+    }
+
+
+    public static boolean isJavaLangObject(DexClass dexClass) {
+        assert dexClass != null;
+        return JAVA_LANG_OBJECT.equals(dexClass.getName());
+    }
+}
diff --git a/tools/signature-tools/src/signature/converter/dex/FieldPool.java b/tools/signature-tools/src/signature/converter/dex/FieldPool.java
new file mode 100644
index 0000000..6587820
--- /dev/null
+++ b/tools/signature-tools/src/signature/converter/dex/FieldPool.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter.dex;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import signature.model.impl.SigEnumConstant;
+import signature.model.impl.SigField;
+
+public class FieldPool {
+
+    private Map<FieldKey, SigField> fieldStore;
+    private Map<FieldKey, SigEnumConstant> constantStore;
+
+    public FieldPool() {
+        fieldStore = new HashMap<FieldKey, SigField>();
+        constantStore = new HashMap<FieldKey, SigEnumConstant>();
+    }
+
+    private static class FieldKey {
+        private final String qualifiedClassName;
+        private final String fieldName;
+
+        public FieldKey(String qualifiedClassName, String fieldName) {
+            this.qualifiedClassName = qualifiedClassName;
+            this.fieldName = fieldName;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = prime * fieldName.hashCode();
+            result = prime * result + qualifiedClassName.hashCode();
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            FieldKey other = (FieldKey) obj;
+            if (!fieldName.equals(other.fieldName)) {
+                return false;
+            }
+            if (!qualifiedClassName.equals(other.qualifiedClassName)) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    public SigField getField(String qualifiedClassName, String fieldName) {
+        FieldKey key = new FieldKey(qualifiedClassName, fieldName);
+        SigField sigField = fieldStore.get(key);
+        if (sigField == null) {
+            sigField = new SigField(fieldName);
+            fieldStore.put(key, sigField);
+        }
+        return sigField;
+    }
+
+    public SigEnumConstant getEnumConstant(String qualifiedName,
+            String fieldName) {
+        FieldKey key = new FieldKey(qualifiedName, fieldName);
+        SigEnumConstant sigField = constantStore.get(key);
+        if (sigField == null) {
+            sigField = new SigEnumConstant(fieldName);
+            constantStore.put(key, sigField);
+        }
+        return sigField;
+    }
+
+}
diff --git a/tools/signature-tools/src/signature/converter/dex/GenericSignatureParser.java b/tools/signature-tools/src/signature/converter/dex/GenericSignatureParser.java
new file mode 100644
index 0000000..773e2fc
--- /dev/null
+++ b/tools/signature-tools/src/signature/converter/dex/GenericSignatureParser.java
@@ -0,0 +1,651 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter.dex;
+
+import static signature.converter.dex.DexUtil.getClassName;
+import static signature.converter.dex.DexUtil.getPackageName;
+import signature.model.IClassDefinition;
+import signature.model.IClassReference;
+import signature.model.IConstructor;
+import signature.model.IGenericDeclaration;
+import signature.model.IMethod;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+import signature.model.ITypeVariableReference;
+import signature.model.impl.SigArrayType;
+import signature.model.impl.SigParameterizedType;
+import signature.model.impl.SigPrimitiveType;
+import signature.model.impl.SigTypeVariableDefinition;
+import signature.model.impl.SigWildcardType;
+import signature.model.impl.Uninitialized;
+import signature.model.util.ITypeFactory;
+
+import java.lang.reflect.GenericSignatureFormatError;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implements a parser for the generics signature attribute. Uses a top-down,
+ * recursive descent parsing approach for the following grammar:
+ * 
+ * <pre>
+ * ClassSignature ::=
+ *     OptFormalTypeParams SuperclassSignature {SuperinterfaceSignature}.
+ * SuperclassSignature ::= ClassTypeSignature.
+ * SuperinterfaceSignature ::= ClassTypeSignature.
+ *
+ * OptFormalTypeParams ::=
+ *     ["<" FormalTypeParameter {FormalTypeParameter} ">"].
+ *
+ * FormalTypeParameter ::= Ident ClassBound {InterfaceBound}.
+ * ClassBound ::= ":" [FieldTypeSignature].
+ * InterfaceBound ::= ":" FieldTypeSignature.
+ *
+ * FieldTypeSignature ::=
+ *     ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature.
+ * ArrayTypeSignature ::= "[" TypSignature.
+ *
+ * ClassTypeSignature ::=
+ *     "L" {Ident "/"} Ident OptTypeArguments {"." Ident OptTypeArguments} ";".
+ *
+ * OptTypeArguments ::= "<" TypeArgument {TypeArgument} ">".
+ *
+ * TypeArgument ::= ([WildcardIndicator] FieldTypeSignature) | "*".
+ * WildcardIndicator ::= "+" | "-".
+ *
+ * TypeVariableSignature ::= "T" Ident ";".
+ *
+ * TypSignature ::= FieldTypeSignature | BaseType.
+ * BaseType ::= "B" | "C" | "D" | "F" | "I" | "J" | "S" | "Z".
+ *
+ * MethodTypeSignature ::=
+ *     OptFormalTypeParams "(" {TypeSignature} ")" ReturnType {ThrowsSignature}.
+ * ThrowsSignature ::= ("^" ClassTypeSignature) | ("^" TypeVariableSignature).
+ *
+ * ReturnType ::= TypSignature | VoidDescriptor.
+ * VoidDescriptor ::= "V".
+ * </pre>
+ */
+public class GenericSignatureParser {
+
+    public List<ITypeReference> exceptionTypes;
+    public List<ITypeReference> parameterTypes;
+    public List<ITypeVariableDefinition> formalTypeParameters;
+    public ITypeReference returnType;
+    public ITypeReference fieldType;
+    public List<ITypeReference> interfaceTypes;
+    public ITypeReference superclassType;
+
+    private IGenericDeclaration genericDecl;
+
+    /*
+     * Parser:
+     */
+    private char symbol; // 0: eof; else valid term symbol or first char of
+    // identifier.
+    private String identifier;
+
+
+    /*
+     * Scanner: eof is private to the scan methods and it's set only when a scan
+     * is issued at the end of the buffer.
+     */
+    private boolean eof;
+
+    private char[] buffer;
+    private int pos;
+
+    private final ITypeFactory factory;
+    private final IClassInitializer classFinder;
+    private boolean parseForField;
+
+
+    public GenericSignatureParser(ITypeFactory factory,
+            IClassInitializer classFinder) {
+        this.factory = factory;
+        this.classFinder = classFinder;
+    }
+
+    private void setInput(IGenericDeclaration genericDecl, String input) {
+        if (input != null) {
+            this.genericDecl = genericDecl;
+            this.buffer = input.toCharArray();
+            this.eof = false;
+            scanSymbol();
+        } else {
+            this.eof = true;
+        }
+    }
+
+    public ITypeReference parseNonGenericType(String typeSignature) {
+        setInput(null, typeSignature);
+        ITypeReference type = parsePrimitiveType();
+        if (type == null) {
+            type = parseFieldTypeSignature();
+        }
+        return type;
+    }
+
+    public ITypeReference parseNonGenericReturnType(String typeSignature) {
+        setInput(null, typeSignature);
+        ITypeReference returnType = parsePrimitiveType();
+        if (returnType == null) {
+            returnType = parseReturnType();
+        }
+        return returnType;
+    }
+
+    private ITypeReference parsePrimitiveType() {
+        switch (symbol) {
+        case 'B':
+            scanSymbol();
+            return SigPrimitiveType.BYTE_TYPE;
+        case 'C':
+            scanSymbol();
+            return SigPrimitiveType.CHAR_TYPE;
+        case 'D':
+            scanSymbol();
+            return SigPrimitiveType.DOUBLE_TYPE;
+        case 'F':
+            scanSymbol();
+            return SigPrimitiveType.FLOAT_TYPE;
+        case 'I':
+            scanSymbol();
+            return SigPrimitiveType.INT_TYPE;
+        case 'J':
+            scanSymbol();
+            return SigPrimitiveType.LONG_TYPE;
+        case 'S':
+            scanSymbol();
+            return SigPrimitiveType.SHORT_TYPE;
+        case 'Z':
+            scanSymbol();
+            return SigPrimitiveType.BOOLEAN_TYPE;
+        default:
+            return null;
+        }
+    }
+
+    /**
+     * Parses the generic signature of a class and creates the data structure
+     * representing the signature.
+     * 
+     * @param classToProcess
+     *            the GenericDeclaration calling this method
+     * @param signature
+     *            the generic signature of the class
+     */
+    public void parseForClass(IClassDefinition classToProcess,
+            String signature) {
+        setInput(classToProcess, signature);
+        if (!eof) {
+            parseClassSignature();
+        } else {
+            throw new IllegalStateException("Generic signature is invalid!");
+        }
+    }
+
+    /**
+     * Parses the generic signature of a method and creates the data structure
+     * representing the signature.
+     * 
+     * @param genericDecl
+     *            the GenericDeclaration calling this method
+     * @param signature
+     *            the generic signature of the class
+     */
+    public void parseForMethod(IMethod genericDecl, String signature) {
+        setInput(genericDecl, signature);
+        if (!eof) {
+            parseMethodTypeSignature();
+        } else {
+            throw new IllegalStateException("Generic signature is invalid!");
+        }
+    }
+
+    /**
+     * Parses the generic signature of a constructor and creates the data
+     * structure representing the signature.
+     * 
+     * @param genericDecl
+     *            the GenericDeclaration calling this method
+     * @param signature
+     *            the generic signature of the class
+     */
+    public void parseForConstructor(IConstructor genericDecl,
+            String signature) {
+        setInput(genericDecl, signature);
+        if (!eof) {
+            parseMethodTypeSignature();
+        } else {
+            throw new IllegalStateException("Generic signature is invalid!");
+        }
+    }
+
+    /**
+     * Parses the generic signature of a field and creates the data structure
+     * representing the signature.
+     * 
+     * @param genericDecl
+     *            the GenericDeclaration calling this method
+     * @param signature
+     *            the generic signature of the class
+     */
+    public void parseForField(IClassDefinition genericDecl, String signature) {
+        parseForField = true;
+        setInput(genericDecl, signature);
+        try {
+            if (!eof) {
+                this.fieldType = parseFieldTypeSignature();
+            } else {
+                throw new IllegalStateException(
+                        "Generic signature is invalid!");
+            }
+        } finally {
+            parseForField = false;
+        }
+    }
+
+    private void parseClassSignature() {
+        // ClassSignature ::=
+        // OptFormalTypeParameters SuperclassSignature
+        // {SuperinterfaceSignature}.
+
+        parseOptFormalTypeParameters();
+
+        // SuperclassSignature ::= ClassTypeSignature.
+        this.superclassType = parseClassTypeSignature();
+
+        interfaceTypes = new ArrayList<ITypeReference>(16);
+        while (symbol > 0) {
+            // SuperinterfaceSignature ::= ClassTypeSignature.
+            interfaceTypes.add(parseClassTypeSignature());
+        }
+    }
+
+    private void parseOptFormalTypeParameters() {
+        // OptFormalTypeParameters ::=
+        // ["<" FormalTypeParameter {FormalTypeParameter} ">"].
+
+        List<ITypeVariableDefinition> typeParameters =
+                new ArrayList<ITypeVariableDefinition>();
+
+        if (symbol == '<') {
+            scanSymbol();
+            typeParameters.add(parseFormalTypeParameter());
+            while ((symbol != '>') && (symbol > 0)) {
+                typeParameters.add(parseFormalTypeParameter());
+            }
+            expect('>');
+        }
+
+        formalTypeParameters = typeParameters;
+    }
+
+    private SigTypeVariableDefinition parseFormalTypeParameter() {
+        // FormalTypeParameter ::= Ident ClassBound {InterfaceBound}.
+
+        scanIdentifier();
+        String name = identifier.intern();
+        SigTypeVariableDefinition typeVariable = factory.getTypeVariable(name,
+                genericDecl);
+
+        List<ITypeReference> bounds = new ArrayList<ITypeReference>();
+
+        // ClassBound ::= ":" [FieldTypeSignature].
+        expect(':');
+        if (symbol == 'L' || symbol == '[' || symbol == 'T') {
+            bounds.add(parseFieldTypeSignature());
+        }
+
+        while (symbol == ':') {
+            // InterfaceBound ::= ":" FieldTypeSignature.
+            scanSymbol();
+            bounds.add(parseFieldTypeSignature());
+        }
+        typeVariable.setUpperBounds(bounds);
+        return typeVariable;
+    }
+
+    /**
+     * Returns the generic declaration for the type variable with the specified
+     * name.
+     * 
+     * @param variableName
+     *            the name of the type variable
+     * @param declaration
+     *            the declaration to start searching
+     * @return the declaration which defines the specified type variable
+     */
+    private IGenericDeclaration getDeclarationOfTypeVariable(
+            String variableName, IClassDefinition declaration) {
+        assert variableName != null;
+        assert declaration != null;
+
+        if (!Uninitialized.isInitialized(declaration.getTypeParameters())) {
+            declaration = classFinder.initializeClass(declaration
+                    .getPackageName(), declaration.getName());
+        }
+
+        for (ITypeVariableDefinition typeVariable : declaration
+                .getTypeParameters()) {
+            if (variableName.equals(typeVariable.getName())) {
+                return declaration;
+            }
+        }
+        return getDeclarationOfTypeVariable(variableName, declaration
+                .getDeclaringClass());
+    }
+
+    private ITypeReference parseFieldTypeSignature() {
+        // FieldTypeSignature ::= ClassTypeSignature | ArrayTypeSignature
+        // | TypeVariableSignature.
+
+        switch (symbol) {
+        case 'L':
+            return parseClassTypeSignature();
+        case '[':
+            // ArrayTypeSignature ::= "[" TypSignature.
+            scanSymbol();
+            SigArrayType arrayType = factory.getArrayType(parseTypeSignature());
+            return arrayType;
+        case 'T':
+            return parseTypeVariableSignature();
+        default:
+            throw new GenericSignatureFormatError();
+        }
+    }
+
+    private ITypeReference parseClassTypeSignature() {
+        // ClassTypeSignature ::= "L" {Ident "/"} Ident
+        // OptTypeArguments {"." Ident OptTypeArguments} ";".
+
+        expect('L');
+
+        StringBuilder qualIdent = new StringBuilder("L");
+        scanIdentifier();
+        while (symbol == '/') {
+            scanSymbol();
+            qualIdent.append(identifier).append("/");
+            scanIdentifier();
+        }
+
+        qualIdent.append(this.identifier);
+
+
+        List<ITypeReference> typeArgs = parseOptTypeArguments();
+
+        ITypeReference parentType = null;
+
+        String packageName = getPackageName(qualIdent.toString() + ";");
+        String className = getClassName(qualIdent.toString() + ";");
+
+        if (typeArgs.isEmpty()) {
+            parentType = factory.getClassReference(packageName, className);
+        } else {
+            IClassReference rawType = factory.getClassReference(packageName,
+                    className);
+            SigParameterizedType parameterizedType = factory
+                    .getParameterizedType(null, rawType, typeArgs);
+            parentType = parameterizedType;
+        }
+
+        ITypeReference typeToReturn = parentType;
+
+
+        // if owner type is a parameterized type, the types are separated by '.'
+        while (symbol == '.') {
+            // Deal with Member Classes:
+            scanSymbol();
+            scanIdentifier();
+            qualIdent.append("$").append(identifier);
+            typeArgs = parseOptTypeArguments();
+            ITypeReference memberType = null;
+
+            packageName = getPackageName(qualIdent.toString() + ";");
+            className = getClassName(qualIdent.toString() + ";");
+
+            if (typeArgs.isEmpty()) {
+                memberType = factory.getClassReference(packageName, className);
+            } else {
+                IClassReference rawType = factory.getClassReference(
+                        packageName, className);
+                SigParameterizedType parameterizedType = factory
+                        .getParameterizedType(parentType, rawType, typeArgs);
+                memberType = parameterizedType;
+            }
+            typeToReturn = memberType;
+        }
+
+        expect(';');
+
+        return typeToReturn;
+    }
+
+    private List<ITypeReference> parseOptTypeArguments() {
+        // OptTypeArguments ::= "<" TypeArgument {TypeArgument} ">".
+
+        List<ITypeReference> typeArgs = new ArrayList<ITypeReference>(8);
+        if (symbol == '<') {
+            scanSymbol();
+
+            typeArgs.add(parseTypeArgument());
+            while ((symbol != '>') && (symbol > 0)) {
+                typeArgs.add(parseTypeArgument());
+            }
+            expect('>');
+        }
+        return typeArgs;
+    }
+
+    private ITypeReference parseTypeArgument() {
+        // TypeArgument ::= (["+" | "-"] FieldTypeSignature) | "*".
+        List<ITypeReference> extendsBound = new ArrayList<ITypeReference>(1);
+        ITypeReference superBound = null;
+        if (symbol == '*') {
+            scanSymbol();
+            extendsBound.add(factory.getClassReference("java.lang", "Object"));
+            SigWildcardType wildcardType = factory.getWildcardType(superBound,
+                    extendsBound);
+            return wildcardType;
+        } else if (symbol == '+') {
+            scanSymbol();
+            extendsBound.add(parseFieldTypeSignature());
+            SigWildcardType wildcardType = factory.getWildcardType(superBound,
+                    extendsBound);
+            return wildcardType;
+        } else if (symbol == '-') {
+            scanSymbol();
+            superBound = parseFieldTypeSignature();
+            extendsBound.add(factory.getClassReference("java.lang", "Object"));
+            SigWildcardType wildcardType = factory.getWildcardType(superBound,
+                    extendsBound);
+            return wildcardType;
+        } else {
+            return parseFieldTypeSignature();
+        }
+    }
+
+    private ITypeVariableReference parseTypeVariableSignature() {
+        // TypeVariableSignature ::= "T" Ident ";".
+        expect('T');
+        scanIdentifier();
+        expect(';');
+
+        IGenericDeclaration declaration = genericDecl;
+
+        if (!factory.containsTypeVariableDefinition(identifier, declaration)) {
+            // since a field is not a generic declaration, i need to treat it
+            // differently.
+            // the generic declaration
+            if (parseForField) {
+                declaration = getDeclarationOfTypeVariable(identifier,
+                        (IClassDefinition) genericDecl);
+            } else {
+                declaration = getDeclarationOfTypeVariable(identifier,
+                        genericDecl.getDeclaringClass());
+            }
+            // just create type variable
+            factory.getTypeVariable(identifier, declaration);
+        }
+
+        return factory.getTypeVariableReference(identifier, declaration);
+    }
+
+    private ITypeReference parseTypeSignature() {
+        switch (symbol) {
+        case 'B':
+            scanSymbol();
+            return SigPrimitiveType.BYTE_TYPE;
+        case 'C':
+            scanSymbol();
+            return SigPrimitiveType.CHAR_TYPE;
+        case 'D':
+            scanSymbol();
+            return SigPrimitiveType.DOUBLE_TYPE;
+        case 'F':
+            scanSymbol();
+            return SigPrimitiveType.FLOAT_TYPE;
+        case 'I':
+            scanSymbol();
+            return SigPrimitiveType.INT_TYPE;
+        case 'J':
+            scanSymbol();
+            return SigPrimitiveType.LONG_TYPE;
+        case 'S':
+            scanSymbol();
+            return SigPrimitiveType.SHORT_TYPE;
+        case 'Z':
+            scanSymbol();
+            return SigPrimitiveType.BOOLEAN_TYPE;
+        default:
+            // Not an elementary type, but a FieldTypeSignature.
+            return parseFieldTypeSignature();
+        }
+    }
+
+    private void parseMethodTypeSignature() {
+        // MethodTypeSignature ::= [FormalTypeParameters]
+        // "(" {TypeSignature} ")" ReturnType {ThrowsSignature}.
+
+        parseOptFormalTypeParameters();
+
+        parameterTypes = new ArrayList<ITypeReference>(16);
+        expect('(');
+        while (symbol != ')' && (symbol > 0)) {
+            parameterTypes.add(parseTypeSignature());
+        }
+        expect(')');
+
+        returnType = parseReturnType();
+
+        exceptionTypes = new ArrayList<ITypeReference>(8);
+        while (symbol == '^') {
+            scanSymbol();
+
+            // ThrowsSignature ::= ("^" ClassTypeSignature) |
+            // ("^" TypeVariableSignature).
+            if (symbol == 'T') {
+                exceptionTypes.add(parseTypeVariableSignature());
+            } else {
+                exceptionTypes.add(parseClassTypeSignature());
+            }
+        }
+    }
+
+    private ITypeReference parseReturnType() {
+        // ReturnType ::= TypeSignature | "V".
+        if (symbol != 'V') {
+            return parseTypeSignature();
+        } else {
+            scanSymbol();
+            return SigPrimitiveType.VOID_TYPE;
+        }
+    }
+
+
+    //
+    // Scanner:
+    //
+
+    private void scanSymbol() {
+        if (!eof) {
+            if (pos < buffer.length) {
+                symbol = buffer[pos];
+                pos++;
+            } else {
+                symbol = 0;
+                eof = true;
+            }
+        } else {
+            throw new GenericSignatureFormatError();
+        }
+    }
+
+    private void expect(char c) {
+        if (symbol == c) {
+            scanSymbol();
+        } else {
+            throw new GenericSignatureFormatError();
+        }
+    }
+
+    private boolean isStopSymbol(char ch) {
+        switch (ch) {
+        case ':':
+        case '/':
+        case ';':
+        case '<':
+        case '.':
+            return true;
+        }
+        return false;
+    }
+
+    // PRE: symbol is the first char of the identifier.
+    // POST: symbol = the next symbol AFTER the identifier.
+    private void scanIdentifier() {
+        if (!eof) {
+            StringBuilder identBuf = new StringBuilder(32);
+            if (!isStopSymbol(symbol)) {
+                identBuf.append(symbol);
+                do {
+                    char ch = buffer[pos];
+                    if ((ch >= 'a') && (ch <= 'z') || (ch >= 'A')
+                            && (ch <= 'Z') || !isStopSymbol(ch)) {
+                        identBuf.append(buffer[pos]);
+                        pos++;
+                    } else {
+                        identifier = identBuf.toString();
+                        scanSymbol();
+                        return;
+                    }
+                } while (pos != buffer.length);
+                identifier = identBuf.toString();
+                symbol = 0;
+                eof = true;
+            } else {
+                // Ident starts with incorrect char.
+                symbol = 0;
+                eof = true;
+                throw new GenericSignatureFormatError();
+            }
+        } else {
+            throw new GenericSignatureFormatError();
+        }
+    }
+}
diff --git a/tools/signature-tools/src/signature/converter/dex/IClassInitializer.java b/tools/signature-tools/src/signature/converter/dex/IClassInitializer.java
new file mode 100644
index 0000000..935ca49
--- /dev/null
+++ b/tools/signature-tools/src/signature/converter/dex/IClassInitializer.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter.dex;
+
+import signature.model.IClassDefinition;
+
+public interface IClassInitializer {
+    IClassDefinition initializeClass(String packageName, String className);
+}
diff --git a/tools/signature-tools/src/signature/converter/doclet/DocletFactory.java b/tools/signature-tools/src/signature/converter/doclet/DocletFactory.java
new file mode 100644
index 0000000..ea757db
--- /dev/null
+++ b/tools/signature-tools/src/signature/converter/doclet/DocletFactory.java
@@ -0,0 +1,124 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * 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 signature.converter.doclet;

+

+import java.io.IOException;

+import java.io.PrintWriter;

+import java.io.StringWriter;

+import java.lang.reflect.Constructor;

+import java.util.Set;

+

+import signature.converter.Visibility;

+import signature.io.IApiLoader;

+import signature.model.IApi;

+

+import com.sun.javadoc.RootDoc;

+import com.sun.tools.javac.util.Context;

+import com.sun.tools.javac.util.ListBuffer;

+import com.sun.tools.javac.util.Options;

+import com.sun.tools.javadoc.JavadocTool;

+import com.sun.tools.javadoc.Messager;

+import com.sun.tools.javadoc.ModifierFilter;

+import com.sun.tools.javadoc.RootDocImpl;

+

+public class DocletFactory implements IApiLoader {

+

+    public IApi loadApi(String name, Visibility visibility,

+            Set<String> fileNames, Set<String> packageNames) throws

+            IOException {

+        for (String packageName : packageNames) {

+            if (packageName.length() == 0)

+                throw new IllegalArgumentException(

+                        "default package not supported by DocletFactory");

+        }

+        StringBuffer buf = new StringBuffer();

+        for (String filename : fileNames) {

+            buf.append(filename);

+            buf.append(":");

+        }

+        String sourcepath = buf.substring(0, buf.length() - 1);

+        RootDoc root = getRootDoc(visibility, sourcepath, packageNames);

+        DocletToSigConverter converter = new DocletToSigConverter();

+        IApi api = converter.convertDocletRoot(name, root, visibility,

+                packageNames);

+        return api;

+    }

+

+    private static RootDoc getRootDoc(Visibility visibility, String sourcepath,

+            java.util.Set<String> packages) throws IOException {

+        long accessModifier = 0;

+        switch (visibility) {

+        case PRIVATE:

+            accessModifier |= com.sun.tools.javac.code.Flags.PRIVATE; // 0x2

+        case PACKAGE:                                              // 0x80000000

+            accessModifier |= com.sun.tools.javadoc.ModifierFilter.PACKAGE;

+        case PROTECTED:

+            accessModifier |= com.sun.tools.javac.code.Flags.PROTECTED; // 0x4

+        case PUBLIC:

+            accessModifier |= com.sun.tools.javac.code.Flags.PUBLIC; // 0x1

+        }

+

+        ModifierFilter showAccess = new ModifierFilter(accessModifier);

+        boolean breakiterator = false;

+        boolean quiet = false;

+        boolean legacy = false;

+        boolean docClasses = false;

+

+        String docLocale = "";

+        String encoding = null;

+        ListBuffer<String> javaNames = new ListBuffer<String>();

+        for (String p : packages)

+            javaNames.append(p);

+

+        ListBuffer<String[]> options = new ListBuffer<String[]>();

+

+        options.append(new String[] {"-sourcepath", sourcepath});

+

+        ListBuffer<String> subPackages = new ListBuffer<String>();

+        ListBuffer<String> excludedPackages = new ListBuffer<String>();

+

+        Context context = new Context();

+        Options compOpts = Options.instance(context);

+        compOpts.put("-sourcepath", sourcepath);

+

+        Constructor<Messager> c;

+        try {

+            // c = Messager.class.getDeclaredConstructor(Context.class,

+            // String.class);

+            // c.setAccessible(true);

+            // c.newInstance(context, "SigTest");

+            c = Messager.class.getDeclaredConstructor(Context.class,

+                    String.class, PrintWriter.class, PrintWriter.class,

+                    PrintWriter.class);

+            c.setAccessible(true);

+            PrintWriter err = new PrintWriter(new StringWriter());

+            PrintWriter warn = new PrintWriter(new StringWriter());

+            PrintWriter notice = new PrintWriter(new StringWriter());

+            c.newInstance(context, "SigTest", err, warn, notice);

+        } catch (Exception e) {

+            throw new RuntimeException(e);

+        }

+

+        JavadocTool comp = JavadocTool.make0(context);

+        RootDocImpl root = comp.getRootDocImpl(docLocale, encoding, showAccess,

+                javaNames.toList(), options.toList(), breakiterator,

+                subPackages.toList(), excludedPackages.toList(), docClasses,

+                legacy, quiet);

+        return root;

+    }

+

+}

diff --git a/tools/signature-tools/src/signature/converter/doclet/DocletToSigConverter.java b/tools/signature-tools/src/signature/converter/doclet/DocletToSigConverter.java
new file mode 100644
index 0000000..f9ebe77
--- /dev/null
+++ b/tools/signature-tools/src/signature/converter/doclet/DocletToSigConverter.java
@@ -0,0 +1,636 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * 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 signature.converter.doclet;

+

+import java.util.EnumSet;

+import java.util.HashMap;

+import java.util.HashSet;

+import java.util.LinkedList;

+import java.util.List;

+import java.util.Map;

+import java.util.Set;

+import java.util.Stack;

+import java.util.Map.Entry;

+

+import signature.converter.Visibility;

+import signature.model.IAnnotation;

+import signature.model.IAnnotationElement;

+import signature.model.IAnnotationField;

+import signature.model.IApi;

+import signature.model.IClassDefinition;

+import signature.model.IClassReference;

+import signature.model.IConstructor;

+import signature.model.IEnumConstant;

+import signature.model.IField;

+import signature.model.IGenericDeclaration;

+import signature.model.IMethod;

+import signature.model.IPackage;

+import signature.model.IParameter;

+import signature.model.ITypeReference;

+import signature.model.ITypeVariableDefinition;

+import signature.model.ITypeVariableReference;

+import signature.model.Kind;

+import signature.model.Modifier;

+import signature.model.impl.SigAnnotation;

+import signature.model.impl.SigAnnotationElement;

+import signature.model.impl.SigAnnotationField;

+import signature.model.impl.SigApi;

+import signature.model.impl.SigClassDefinition;

+import signature.model.impl.SigClassReference;

+import signature.model.impl.SigConstructor;

+import signature.model.impl.SigEnumConstant;

+import signature.model.impl.SigExecutableMember;

+import signature.model.impl.SigField;

+import signature.model.impl.SigMethod;

+import signature.model.impl.SigPackage;

+import signature.model.impl.SigParameter;

+import signature.model.impl.SigPrimitiveType;

+import signature.model.impl.SigTypeVariableDefinition;

+import signature.model.impl.SigTypeVariableReference;

+import signature.model.util.TypePool;

+

+import com.sun.javadoc.AnnotationDesc;

+import com.sun.javadoc.AnnotationTypeDoc;

+import com.sun.javadoc.AnnotationTypeElementDoc;

+import com.sun.javadoc.AnnotationValue;

+import com.sun.javadoc.ClassDoc;

+import com.sun.javadoc.ConstructorDoc;

+import com.sun.javadoc.ExecutableMemberDoc;

+import com.sun.javadoc.FieldDoc;

+import com.sun.javadoc.MethodDoc;

+import com.sun.javadoc.PackageDoc;

+import com.sun.javadoc.Parameter;

+import com.sun.javadoc.ParameterizedType;

+import com.sun.javadoc.ProgramElementDoc;

+import com.sun.javadoc.RootDoc;

+import com.sun.javadoc.Type;

+import com.sun.javadoc.TypeVariable;

+import com.sun.javadoc.WildcardType;

+import com.sun.javadoc.AnnotationDesc.ElementValuePair;

+

+public class DocletToSigConverter {

+

+    TypePool pool;

+    Set<String> packageNames;

+

+    /**

+     * Converts the signature information javadoc knows about into a

+     * signature.model.ISources structure.

+     */

+    public IApi convertDocletRoot(String name, RootDoc root,

+            Visibility visibility, Set<String> packageNames) {

+        this.pool = new TypePool();

+        this.packageNames = packageNames;

+

+        Set<IPackage> packages = new HashSet<IPackage>();

+

+        for (PackageDoc pack : root.specifiedPackages()) {

+            assert packageNames.contains(pack.name());

+            packages.add(convertPackage(pack));

+        }

+

+        SigApi sources = new SigApi(name, visibility);

+        sources.setPackages(packages);

+        return sources;

+    }

+

+    private IPackage convertPackage(PackageDoc packageDoc) {

+        Set<IClassDefinition> classes = new HashSet<IClassDefinition>();

+        for (ClassDoc clazz : packageDoc.allClasses()) {

+            // classes.add((IClass)convertType(clazz));

+            classes.add(convertClass(clazz));

+        }

+

+        SigPackage p = new SigPackage(packageDoc.name());

+        p.setClasses(classes);

+        p.setAnnotations(convertAnnotations(packageDoc.annotations()));

+        return p;

+    }

+

+    private SigClassDefinition convertClass(ClassDoc classDoc) {

+

+        SigClassDefinition c = pool.getClass(classDoc.containingPackage()

+                .name(), classDoc.name());

+        if (c.getKind() != Kind.UNINITIALIZED) return c;

+

+        if (classDoc.isEnum())

+            c.setKind(Kind.ENUM);

+        else if (classDoc.isInterface())

+            c.setKind(Kind.INTERFACE);

+        else if (classDoc.isClass())

+            c.setKind(Kind.CLASS);

+        else if (classDoc.isAnnotationType()) c.setKind(Kind.ANNOTATION);

+

+        if (!packageNames.contains(c.getPackageName())) {

+            // no additional conversion for this class is necessary

+            initializeClass(c);

+            return c;

+        }

+

+        c.setModifiers(convertModifiers(classDoc.modifierSpecifier()));

+        if (Kind.INTERFACE.equals(c.getKind())

+                || Kind.ANNOTATION.equals(c.getKind())) {

+            c.getModifiers().add(Modifier.ABSTRACT);

+        }

+

+        // superclass may be a class or a parameterized type (e.g. extends

+        // List<String>),

+        // may also be null if classDoc is an interface

+        Type superclassType = classDoc.superclassType();

+        if (superclassType != null) {

+            c.setSuperClass(convertTypeReference(classDoc.superclassType()));

+        } else {

+            c.setSuperClass(null);

+        }

+

+        Set<ITypeReference> interfaces = new HashSet<ITypeReference>();

+        for (Type interfaceType : classDoc.interfaceTypes()) {

+            interfaces.add(convertTypeReference(interfaceType));

+        }

+        c.setInterfaces(interfaces);

+

+        ClassDoc containingClass = classDoc.containingClass();

+        if (containingClass != null)

+            c.setDeclaringClass(convertClass(containingClass));

+        else

+            c.setDeclaringClass(null);

+

+        Set<IClassDefinition> innerClasses = new HashSet<IClassDefinition>();

+        for (ClassDoc innerClass : classDoc.innerClasses()) {

+            innerClasses.add(convertClass(innerClass));

+        }

+        c.setInnerClasses(innerClasses);

+

+        Set<IConstructor> constructors = new HashSet<IConstructor>();

+        for (ConstructorDoc constructor : classDoc.constructors()) {

+            constructors.add(convertConstructor(constructor));

+        }

+        c.setConstructors(constructors);

+

+        Set<IMethod> methods = new HashSet<IMethod>();

+        for (MethodDoc method : classDoc.methods()) {

+            methods.add(convertMethod(method));

+        }

+        c.setMethods(methods);

+

+        Set<IField> fields = new HashSet<IField>();

+        for (FieldDoc field : classDoc.fields()) {

+            fields.add(convertField(field));

+        }

+        c.setFields(fields);

+

+        Set<IEnumConstant> enumConstants = new HashSet<IEnumConstant>();

+        int ordinal = 0;

+        for (FieldDoc enumConstant : classDoc.enumConstants()) {

+            enumConstants.add(convertEnumConstant(enumConstant, ordinal++));

+        }

+        c.setEnumConstants(enumConstants);

+

+        List<ITypeVariableDefinition> typeParameters =

+                new LinkedList<ITypeVariableDefinition>();

+        for (TypeVariable typeVariable : classDoc.typeParameters()) {

+            typeParameters

+                    .add(((ITypeVariableReference) convertTypeReference(

+                            typeVariable)).getTypeVariableDefinition());

+        }

+        c.setTypeParameters(typeParameters);

+

+        if (classDoc.isAnnotationType()) {

+            Map<SigAnnotationField, AnnotationTypeElementDoc> annotationFieldAnnotations =

+                    new HashMap<SigAnnotationField, AnnotationTypeElementDoc>();

+

+            // AnnotationTypeDoc annotationType =

+            // classDoc.asAnnotationTypeDoc(); // bug in Doclet Implementation,

+            // has been reported to sun

+            AnnotationTypeDoc annotationType = (AnnotationTypeDoc) classDoc;

+

+            Set<IAnnotationField> annotationFields =

+                    new HashSet<IAnnotationField>();

+            for (AnnotationTypeElementDoc annotationElement : annotationType

+                    .elements()) {

+                SigAnnotationField annotationField = new SigAnnotationField(

+                        annotationElement.name());

+                annotationField.setModifiers(convertModifiers(annotationElement

+                        .modifierSpecifier()));

+                annotationField.setType(convertTypeReference(annotationElement

+                        .returnType()));

+                annotationField

+                        .setDefaultValue(convertAnnotationValue(

+                                annotationElement.defaultValue()));

+

+                // the annotations on fields are set later because these

+                // annotations may be of

+                // the same type and may use fields which are not yet defined

+                annotationFieldAnnotations.put(annotationField,

+                        annotationElement);

+

+                annotationFields.add(annotationField);

+            }

+            c.setAnnotationFields(annotationFields);

+

+            // set annotation field annotations

+            for (Entry<SigAnnotationField, AnnotationTypeElementDoc> entry :

+                    annotationFieldAnnotations.entrySet()) {

+                entry.getKey().setAnnotations(

+                        convertAnnotations(entry.getValue().annotations()));

+            }

+        } else { // no annotation type

+            c.setAnnotationFields(null);

+        }

+

+        // set class annotations

+        c.setAnnotations(convertAnnotations(classDoc.annotations()));

+

+        return c;

+

+    }

+

+    private Object convertAnnotationValue(AnnotationValue annotationValue) {

+        if (annotationValue == null) {

+            return null;

+        }

+        Object value = annotationValue.value();

+        if (value instanceof Type) {

+            // Type contains primitive types as well, e.g. void.class

+            return convertTypeReference((Type) value);

+        } else if (value instanceof String) {

+            return value;

+        } else if (value instanceof Double || value instanceof Float

+                || value instanceof Long || value instanceof Integer

+                || value instanceof Short || value instanceof Byte

+                || value instanceof Character || value instanceof Boolean) {

+            return value;

+        } else if (value instanceof FieldDoc) {

+            FieldDoc field = (FieldDoc) value;

+            String name = field.name();

+            ITypeReference fieldType = convertTypeReference(field.type());

+            IClassReference fieldClassRef = (IClassReference) fieldType;

+            IClassDefinition fieldClass = fieldClassRef.getClassDefinition();

+

+            assert fieldClass.getKind() == Kind.ENUM;

+            Set<IEnumConstant> constants = fieldClass.getEnumConstants();

+            for (IEnumConstant enumConstant : constants) {

+                if (enumConstant.getName().equals(name)) value = enumConstant;

+            }

+            assert value instanceof IEnumConstant;

+            return value;

+        } else if (value instanceof AnnotationDesc) {

+            return convertAnnotation((AnnotationDesc) value);

+        } else if (value instanceof AnnotationValue) {

+            return convertAnnotationValue((AnnotationValue) value);

+        } else if (value instanceof AnnotationValue[]) {

+            AnnotationValue[] arr = (AnnotationValue[]) value;

+            int length = arr.length;

+            Object[] annotationArray = new Object[length];

+            for (int i = 0; i < length; i++) {

+                annotationArray[i] = convertAnnotationValue(arr[i]);

+            }

+            return annotationArray;

+        } else {

+            throw new RuntimeException("not expected case");

+        }

+    }

+

+    private ITypeReference convertArrayType(Type type) {

+        assert type.asWildcardType() == null;

+        assert type.asAnnotationTypeDoc() == null;

+

+        ITypeReference baseType = null;

+        if (type.asTypeVariable() != null) {

+            baseType = convertTypeReference(type.asTypeVariable());

+        } else if (type.asParameterizedType() != null) {

+            baseType = convertTypeReference(type.asParameterizedType());

+        } else if (type.asClassDoc() != null) {

+            baseType = new SigClassReference(convertClass(type.asClassDoc()));

+        } else if (type.isPrimitive()) {

+            baseType = SigPrimitiveType.valueOfTypeName(type.typeName());

+        } else {

+            throw new RuntimeException(type.toString());

+        }

+

+        ITypeReference arrayType = baseType;

+        int dimension = type.dimension().length() / 2;

+        while (dimension > 0) {

+            arrayType = pool.getArrayType(arrayType);

+            dimension--;

+        }

+

+        return arrayType;

+    }

+

+    private SigTypeVariableDefinition currentTypeVariableDefinition = null;

+

+    private ITypeReference convertTypeReference(Type type) {

+        assert type != null;

+

+        if (!"".equals(type.dimension())) {

+            return convertArrayType(type);

+        }

+

+        ParameterizedType pType = type.asParameterizedType();

+        if (pType != null) {

+            ITypeReference ownerType = null;

+            Type containingType = pType.containingType();

+            if (containingType != null)

+                ownerType = convertTypeReference(containingType);

+            IClassReference rawType = new SigClassReference(convertClass(pType

+                    .asClassDoc()));

+

+            List<ITypeReference> typeArguments =

+                    new LinkedList<ITypeReference>();

+            for (Type typeArgument : pType.typeArguments()) {

+                typeArguments.add(convertTypeReference(typeArgument));

+            }

+

+            if (typeArguments.size() > 0) {

+                return pool.getParameterizedType(ownerType, rawType,

+                        typeArguments);

+            } else {

+                return rawType;

+            }

+        }

+

+        TypeVariable tv = type.asTypeVariable();

+        if (tv != null) {

+            String name = tv.typeName();

+

+            if (currentTypeVariableDefinition != null

+                    && name.equals(currentTypeVariableDefinition.getName()))

+                return new SigTypeVariableReference(

+                        currentTypeVariableDefinition);

+

+            IGenericDeclaration genericDeclaration = null;

+            ProgramElementDoc programElement = tv.owner();

+            if (programElement instanceof ClassDoc) {

+                genericDeclaration = convertClass((ClassDoc) programElement);

+            } else if (programElement instanceof MethodDoc

+                    && currentMethod.size() > 0) {

+                genericDeclaration = currentMethod.peek();

+            } else if (programElement instanceof ConstructorDoc

+                    && currentConstructor.size() > 0) {

+                genericDeclaration = currentConstructor.peek();

+            } else {

+                throw new IllegalStateException("situation not expected");

+            }

+            SigTypeVariableDefinition typeVariable = pool.getTypeVariable(name,

+                    genericDeclaration);

+

+            List<ITypeReference> upperBounds = new LinkedList<ITypeReference>();

+            for (Type upperBound : tv.bounds()) {

+                // we are converting a type variable declaration which is stored

+                // in the

+                // field currentTypeVariableDefinition

+                assert currentTypeVariableDefinition == null;

+                currentTypeVariableDefinition = typeVariable;

+                upperBounds.add(convertTypeReference(upperBound));

+                currentTypeVariableDefinition = null;

+            }

+            if (upperBounds.size() == 0) {

+                // no explicit bounds, use java.lang.Object

+                upperBounds.add(pool.getClassReference("java.lang", "Object"));

+            }

+            typeVariable.setUpperBounds(upperBounds);

+

+            return new SigTypeVariableReference(typeVariable);

+        }

+

+        WildcardType wt = type.asWildcardType();

+        if (wt != null) {

+            ITypeReference lowerBound = null;

+            for (Type superBound : wt.superBounds()) {

+                lowerBound = convertTypeReference(superBound);

+            }

+

+            List<ITypeReference> upperBounds = new LinkedList<ITypeReference>();

+            for (Type upperBound : wt.extendsBounds()) {

+                upperBounds.add(convertTypeReference(upperBound));

+            }

+            if (upperBounds.size() == 0) {

+                // no explicit bounds, use java.lang.Object

+                upperBounds.add(pool.getClassReference("java.lang", "Object"));

+            }

+

+            return pool.getWildcardType(lowerBound, upperBounds);

+        }

+

+        ClassDoc c = type.asClassDoc();

+        if (c != null) {

+            return new SigClassReference(convertClass(c));

+        }

+

+        if (type.isPrimitive()) {

+            return SigPrimitiveType.valueOfTypeName(type.typeName());

+        }

+

+        throw new IllegalStateException(type.toString());

+    }

+

+    private void convertExecutableMember(ExecutableMemberDoc member,

+            SigExecutableMember m) {

+        Set<Modifier> modifiers = convertModifiers(member.modifierSpecifier());

+

+        // Doclet Bug: final values method is not considered as final

+        if (member.containingClass().isEnum() && member.name().equals("values")

+                && member.parameters().length == 0) {

+            modifiers.add(Modifier.FINAL);

+        }

+

+        if (member.containingClass().isInterface()) {

+            modifiers.add(Modifier.ABSTRACT);

+        }

+

+        m.setModifiers(modifiers);

+        m.setAnnotations(convertAnnotations(member.annotations()));

+        m.setDeclaringClass(convertClass(member.containingClass()));

+

+        List<ITypeVariableDefinition> typeParameters =

+                new LinkedList<ITypeVariableDefinition>();

+        for (TypeVariable typeParameter : member.typeParameters()) {

+            String name = typeParameter.typeName();

+            IGenericDeclaration genericDeclaration = null;

+            if (currentMethod.size() > 0)

+                genericDeclaration = currentMethod.peek();

+            else if (currentConstructor.size() > 0)

+                genericDeclaration = currentConstructor.peek();

+            else

+                throw new RuntimeException();

+            SigTypeVariableDefinition p = pool.getTypeVariable(name,

+                    genericDeclaration);

+

+            List<ITypeReference> upperBounds = new LinkedList<ITypeReference>();

+            for (Type u : typeParameter.bounds()) {

+                upperBounds.add(convertTypeReference(u));

+            }

+            p.setUpperBounds(upperBounds);

+            typeParameters.add(p);

+        }

+        m.setTypeParameters(typeParameters);

+

+        List<IParameter> parameters = new LinkedList<IParameter>();

+        for (Parameter parameter : member.parameters()) {

+            SigParameter p = new SigParameter(convertTypeReference(parameter

+                    .type()));

+            p.setAnnotations(convertAnnotations(parameter.annotations()));

+            parameters.add(p);

+        }

+        m.setParameters(parameters);

+

+        Set<ITypeReference> exceptions = new HashSet<ITypeReference>();

+        for (Type exceptionType : member.thrownExceptionTypes()) {

+            exceptions.add(convertTypeReference(exceptionType));

+        }

+        m.setExceptions(exceptions);

+    }

+

+    private Stack<SigMethod> currentMethod = new Stack<SigMethod>();

+

+    private IMethod convertMethod(MethodDoc method) {

+        SigMethod m = new SigMethod(method.name());

+        currentMethod.push(m);

+        convertExecutableMember(method, m);

+        m.setReturnType(convertTypeReference(method.returnType()));

+        currentMethod.pop();

+        return m;

+    }

+

+    private Stack<SigConstructor> currentConstructor =

+            new Stack<SigConstructor>();

+

+    private IConstructor convertConstructor(ConstructorDoc constructor) {

+        SigConstructor c = new SigConstructor(constructor.name());

+        currentConstructor.push(c);

+        convertExecutableMember(constructor, c);

+        currentConstructor.pop();

+        return c;

+    }

+

+    private IField convertField(FieldDoc field) {

+        SigField f = new SigField(field.name());

+        f.setAnnotations(convertAnnotations(field.annotations()));

+        f.setModifiers(convertModifiers(field.modifierSpecifier()));

+        f.setType(convertTypeReference(field.type()));

+        return f;

+    }

+

+    private IEnumConstant convertEnumConstant(FieldDoc enumConstant,

+            int ordinal) {

+        SigEnumConstant ec = new SigEnumConstant(enumConstant.name());

+        ec.setOrdinal(ordinal);

+        ec.setAnnotations(convertAnnotations(enumConstant.annotations()));

+        ec.setModifiers(convertModifiers(enumConstant.modifierSpecifier()));

+        ec.setType(convertTypeReference(enumConstant.type()));

+        return ec;

+    }

+

+    private Set<IAnnotation> convertAnnotations(

+            AnnotationDesc[] annotationDescs) {

+        Set<IAnnotation> annotations = new HashSet<IAnnotation>();

+        for (AnnotationDesc annotationDesc : annotationDescs) {

+            if (!annotationRetentionIsSource(annotationDesc))

+                annotations.add(convertAnnotation(annotationDesc));

+        }

+        return annotations;

+    }

+

+    private boolean annotationRetentionIsSource(AnnotationDesc annotationDesc) {

+        AnnotationTypeDoc type = annotationDesc.annotationType();

+        AnnotationDesc[] annotations = type.annotations();

+        for (AnnotationDesc d : annotations) {

+            if ("java.lang.annotation.Retention".equals(d.annotationType()

+                    .qualifiedName())) {

+                for (ElementValuePair value : d.elementValues()) {

+                    if ("value".equals(value.element().name())) {

+                        return "java.lang.annotation.RetentionPolicy.SOURCE"

+                                .equals(value.value().value().toString());

+                    }

+                }

+            }

+        }

+        // default retention policy is CLASS

+        return false;

+    }

+

+    private IAnnotation convertAnnotation(AnnotationDesc annotationDesc) {

+        SigAnnotation a = new SigAnnotation();

+

+        IClassReference annotationType = (IClassReference) convertTypeReference(

+                annotationDesc.annotationType());

+        a.setType(annotationType);

+

+        Set<IAnnotationElement> elements = new HashSet<IAnnotationElement>();

+        for (AnnotationDesc.ElementValuePair pair : annotationDesc

+                .elementValues()) {

+            SigAnnotationElement element = new SigAnnotationElement();

+            elements.add(element);

+

+            element.setValue(convertAnnotationValue(pair.value()));

+            String name = pair.element().name();

+            for (IAnnotationField field : annotationType.getClassDefinition()

+                    .getAnnotationFields()) {

+                if (field.getName().equals(name)) {

+                    element.setDeclaringField(field);

+                }

+            }

+        }

+        a.setElements(elements);

+        return a;

+    }

+

+    private void initializeClass(SigClassDefinition c) {

+        c.setAnnotationFields(null);

+        c.setAnnotations(null);

+        c.setConstructors(null);

+        c.setDeclaringClass(null);

+        c.setEnumConstants(null);

+        c.setFields(null);

+        c.setInnerClasses(null);

+        c.setInterfaces(null);

+        c.setMethods(null);

+        c.setModifiers(null);

+        c.setSuperClass(null);

+        c.setTypeParameters(null);

+    }

+

+    private Set<Modifier> convertModifiers(int mod) {

+        Set<Modifier> modifiers = EnumSet.noneOf(Modifier.class);

+        if (java.lang.reflect.Modifier.isAbstract(mod))

+            modifiers.add(Modifier.ABSTRACT);

+        if (java.lang.reflect.Modifier.isFinal(mod))

+            modifiers.add(Modifier.FINAL);

+        // if (java.lang.reflect.Modifier.isNative(mod))

+        // modifiers.add(Modifier.NATIVE);

+        if (java.lang.reflect.Modifier.isPrivate(mod))

+            modifiers.add(Modifier.PRIVATE);

+        if (java.lang.reflect.Modifier.isProtected(mod))

+            modifiers.add(Modifier.PROTECTED);

+        if (java.lang.reflect.Modifier.isPublic(mod))

+            modifiers.add(Modifier.PUBLIC);

+        if (java.lang.reflect.Modifier.isStatic(mod))

+            modifiers.add(Modifier.STATIC);

+        // if (java.lang.reflect.Modifier.isStrict(mod))

+        // modifiers.add(Modifier.STRICT);

+        // if (java.lang.reflect.Modifier.isSynchronized(mod))

+        // modifiers.add(Modifier.SYNCHRONIZED);

+        // if (java.lang.reflect.Modifier.isTransient(mod))

+        // modifiers.add(Modifier.TRANSIENT);

+        if (java.lang.reflect.Modifier.isVolatile(mod))

+            modifiers.add(Modifier.VOLATILE);

+

+        return modifiers;

+    }

+

+}

diff --git a/tools/signature-tools/src/signature/io/IApiDeltaExternalizer.java b/tools/signature-tools/src/signature/io/IApiDeltaExternalizer.java
new file mode 100644
index 0000000..bf3cb8b
--- /dev/null
+++ b/tools/signature-tools/src/signature/io/IApiDeltaExternalizer.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.io;
+
+import java.io.IOException;
+
+import signature.compare.model.IApiDelta;
+
+public interface IApiDeltaExternalizer {
+    void externalize(String location, IApiDelta delta) throws IOException;
+}
diff --git a/tools/signature-tools/src/signature/io/IApiExternalizer.java b/tools/signature-tools/src/signature/io/IApiExternalizer.java
new file mode 100644
index 0000000..3bbfbe5
--- /dev/null
+++ b/tools/signature-tools/src/signature/io/IApiExternalizer.java
@@ -0,0 +1,30 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * 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 signature.io;

+

+import signature.model.IApi;

+

+import java.io.IOException;

+

+/**

+ * This interface is used to write API definitions. Possible implementations of

+ * this interface use Java serialization to store the API in binary form on the

+ * disk. An alternative implementation can use ASCII files.

+ */

+public interface IApiExternalizer {

+    void externalizeApi(String loacation, IApi signature) throws IOException;

+}

diff --git a/tools/signature-tools/src/signature/io/IApiLoader.java b/tools/signature-tools/src/signature/io/IApiLoader.java
new file mode 100644
index 0000000..a38fa1a
--- /dev/null
+++ b/tools/signature-tools/src/signature/io/IApiLoader.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.io;
+
+import java.io.IOException;
+import java.util.Set;
+
+import signature.converter.Visibility;
+import signature.model.IApi;
+
+public interface IApiLoader {
+    IApi loadApi(String name, Visibility visibility, Set<String> fileNames,
+            Set<String> packageNames) throws IOException;
+}
diff --git a/tools/signature-tools/src/signature/io/html/ApiOverviewPage.java b/tools/signature-tools/src/signature/io/html/ApiOverviewPage.java
new file mode 100644
index 0000000..d97c092
--- /dev/null
+++ b/tools/signature-tools/src/signature/io/html/ApiOverviewPage.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.io.html;
+
+import org.antlr.stringtemplate.StringTemplate;
+
+import signature.compare.model.IApiDelta;
+import signature.compare.model.IPackageDelta;
+import signature.compare.model.impl.SigDelta;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+public class ApiOverviewPage implements IEmitter {
+
+    private final IApiDelta apiDelta;
+
+    private List<IPackageDelta> removedPackages;
+    private List<IPackageDelta> addedPackages;
+    private List<IPackageDelta> changedPackages;
+    private Map<String, String> commonInfos;
+
+    public ApiOverviewPage(IApiDelta apiDelta,
+            Map<String, String> commonInfos) {
+        this.apiDelta = apiDelta;
+        this.commonInfos = commonInfos;
+        prepareData();
+    }
+
+    private void prepareData() {
+        if (apiDelta.getPackageDeltas().isEmpty()) {
+            commonInfos.put("no_delta", "no_delta");
+        }
+        removedPackages = new ArrayList<IPackageDelta>(SigDelta
+                .getRemoved(apiDelta.getPackageDeltas()));
+        Collections.sort(removedPackages, new PackageByNameComparator());
+
+        addedPackages = new ArrayList<IPackageDelta>(SigDelta.getAdded(apiDelta
+                .getPackageDeltas()));
+        Collections.sort(addedPackages, new PackageByNameComparator());
+
+        changedPackages = new ArrayList<IPackageDelta>(SigDelta
+                .getChanged(apiDelta.getPackageDeltas()));
+        Collections.sort(changedPackages, new PackageByNameComparator());
+    }
+
+    public void writeTo(StringBuilder b) {
+        StringTemplate template = TemplateStore
+                .getStringTemplate("ApiOverviewPage");
+        template.setArgumentContext(commonInfos);
+        template.setAttribute("removed_packages", removedPackages);
+        template.setAttribute("added_packages", addedPackages);
+        template.setAttribute("changed_packages", changedPackages);
+        b.append(template.toString());
+    }
+}
diff --git a/tools/signature-tools/src/signature/io/html/ClassByNameComparator.java b/tools/signature-tools/src/signature/io/html/ClassByNameComparator.java
new file mode 100644
index 0000000..8e23434
--- /dev/null
+++ b/tools/signature-tools/src/signature/io/html/ClassByNameComparator.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.io.html;
+
+import signature.compare.model.IClassDefinitionDelta;
+
+import java.util.Comparator;
+
+public class ClassByNameComparator implements
+        Comparator<IClassDefinitionDelta> {
+
+    public int compare(IClassDefinitionDelta a, IClassDefinitionDelta b) {
+        assert a.getType() == b.getType();
+        if (a.getFrom() != null) {
+            return a.getFrom().getName().compareTo(b.getFrom().getName());
+        } else {
+            return a.getTo().getName().compareTo(b.getTo().getName());
+        }
+    }
+}
diff --git a/tools/signature-tools/src/signature/io/html/ClassOverviewPage.java b/tools/signature-tools/src/signature/io/html/ClassOverviewPage.java
new file mode 100644
index 0000000..6951fb3
--- /dev/null
+++ b/tools/signature-tools/src/signature/io/html/ClassOverviewPage.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.io.html;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Map;
+
+import org.antlr.stringtemplate.StringTemplate;
+
+import signature.compare.model.IAnnotationFieldDelta;
+import signature.compare.model.IClassDefinitionDelta;
+import signature.compare.model.IConstructorDelta;
+import signature.compare.model.IEnumConstantDelta;
+import signature.compare.model.IFieldDelta;
+import signature.compare.model.IMethodDelta;
+import signature.compare.model.impl.SigDelta;
+
+public class ClassOverviewPage implements IEmitter {
+
+    private static final String PAGE = "ClassOverviewPage";
+
+    private final IClassDefinitionDelta classDelta;
+
+    private FieldByNameComparator<IFieldDelta> fieldComparator =
+            new FieldByNameComparator<IFieldDelta>();
+    private ArrayList<IFieldDelta> removedFields;
+    private ArrayList<IFieldDelta> addedFields;
+    private ArrayList<IFieldDelta> changedFields;
+
+    private FieldByNameComparator<IAnnotationFieldDelta> annotationfieldComparator =
+            new FieldByNameComparator<IAnnotationFieldDelta>();
+    private ArrayList<IAnnotationFieldDelta> removedAnnotationFields;
+    private ArrayList<IAnnotationFieldDelta> addedAnnotationFields;
+    private ArrayList<IAnnotationFieldDelta> changedAnnotationFields;
+
+    private FieldByNameComparator<IEnumConstantDelta> enumConstantComparator =
+            new FieldByNameComparator<IEnumConstantDelta>();
+    private ArrayList<IEnumConstantDelta> removedEnumConstants;
+    private ArrayList<IEnumConstantDelta> addedEnumConstants;
+    private ArrayList<IEnumConstantDelta> changedEnumConstants;
+
+    private ExecutableMemberComparator constructorComparator =
+            new ExecutableMemberComparator();
+    private ArrayList<IConstructorDelta> removedConstructors;
+    private ArrayList<IConstructorDelta> addedConstructors;
+    private ArrayList<IConstructorDelta> changedConstructors;
+
+    private ExecutableMemberComparator methodComparator =
+            new ExecutableMemberComparator();
+    private ArrayList<IMethodDelta> removedMethods;
+    private ArrayList<IMethodDelta> addedMethods;
+    private ArrayList<IMethodDelta> changedMethods;
+
+    private final Map<String, String> commonInfos;
+
+    public ClassOverviewPage(IClassDefinitionDelta classDelta,
+            Map<String, String> commonInfos) {
+        this.classDelta = classDelta;
+        this.commonInfos = commonInfos;
+        prepareData();
+    }
+
+    private void prepareData() {
+        if (classDelta.getFieldDeltas() != null) {
+            prepareFieldDeltas();
+        }
+        if (classDelta.getAnnotationFieldDeltas() != null) {
+            prepareAnnotationFieldDeltas();
+        }
+        if (classDelta.getEnumConstantDeltas() != null) {
+            prepareEnumConstantDeltas();
+        }
+        if (classDelta.getConstructorDeltas() != null) {
+            prepareConstructorDeltas();
+        }
+        if (classDelta.getMethodDeltas() != null) {
+            prepareMethodDeltas();
+        }
+    }
+
+    private void prepareFieldDeltas() {
+        removedFields = new ArrayList<IFieldDelta>(SigDelta
+                .getRemoved(classDelta.getFieldDeltas()));
+        Collections.sort(removedFields, fieldComparator);
+
+        addedFields = new ArrayList<IFieldDelta>(SigDelta.getAdded(classDelta
+                .getFieldDeltas()));
+        Collections.sort(addedFields, fieldComparator);
+
+        changedFields = new ArrayList<IFieldDelta>(SigDelta
+                .getChanged(classDelta.getFieldDeltas()));
+        Collections.sort(changedFields, fieldComparator);
+    }
+
+    private void prepareAnnotationFieldDeltas() {
+        removedAnnotationFields = new ArrayList<IAnnotationFieldDelta>(SigDelta
+                .getRemoved(classDelta.getAnnotationFieldDeltas()));
+        Collections.sort(removedAnnotationFields, annotationfieldComparator);
+
+        addedAnnotationFields = new ArrayList<IAnnotationFieldDelta>(SigDelta
+                .getAdded(classDelta.getAnnotationFieldDeltas()));
+        Collections.sort(addedAnnotationFields, annotationfieldComparator);
+
+        changedAnnotationFields = new ArrayList<IAnnotationFieldDelta>(SigDelta
+                .getChanged(classDelta.getAnnotationFieldDeltas()));
+        Collections.sort(changedAnnotationFields, annotationfieldComparator);
+    }
+
+    private void prepareEnumConstantDeltas() {
+        removedEnumConstants = new ArrayList<IEnumConstantDelta>(SigDelta
+                .getRemoved(classDelta.getEnumConstantDeltas()));
+        Collections.sort(removedEnumConstants, enumConstantComparator);
+
+        addedEnumConstants = new ArrayList<IEnumConstantDelta>(SigDelta
+                .getAdded(classDelta.getEnumConstantDeltas()));
+        Collections.sort(addedEnumConstants, enumConstantComparator);
+
+        changedEnumConstants = new ArrayList<IEnumConstantDelta>(SigDelta
+                .getChanged(classDelta.getEnumConstantDeltas()));
+        Collections.sort(changedEnumConstants, enumConstantComparator);
+    }
+
+    private void prepareConstructorDeltas() {
+        removedConstructors = new ArrayList<IConstructorDelta>(SigDelta
+                .getRemoved(classDelta.getConstructorDeltas()));
+        Collections.sort(removedConstructors, constructorComparator);
+
+        addedConstructors = new ArrayList<IConstructorDelta>(SigDelta
+                .getAdded(classDelta.getConstructorDeltas()));
+        Collections.sort(addedConstructors, constructorComparator);
+
+        changedConstructors = new ArrayList<IConstructorDelta>(SigDelta
+                .getChanged(classDelta.getConstructorDeltas()));
+        Collections.sort(changedConstructors, constructorComparator);
+    }
+
+    private void prepareMethodDeltas() {
+        removedMethods = new ArrayList<IMethodDelta>(SigDelta
+                .getRemoved(classDelta.getMethodDeltas()));
+        Collections.sort(removedMethods, methodComparator);
+
+        addedMethods = new ArrayList<IMethodDelta>(SigDelta.getAdded(classDelta
+                .getMethodDeltas()));
+        Collections.sort(addedMethods, methodComparator);
+
+        changedMethods = new ArrayList<IMethodDelta>(SigDelta
+                .getChanged(classDelta.getMethodDeltas()));
+        Collections.sort(changedMethods, methodComparator);
+    }
+
+    public void writeTo(StringBuilder b) {
+        StringTemplate template = TemplateStore.getStringTemplate(PAGE);
+
+        template.setAttribute("class_delta", classDelta);
+        boolean annotationDelta = classDelta.getAnnotationDeltas() != null;
+        boolean modifierDelta = classDelta.getModifierDeltas() != null;
+        boolean typeVariableDelta = classDelta.getTypeVariableDeltas() != null;
+        boolean superClassDelta = classDelta.getSuperClassDelta() != null;
+        boolean interfaceDelta = classDelta.getInterfaceDeltas() != null;
+        boolean hasSignatureDelta = annotationDelta || modifierDelta
+                || typeVariableDelta || superClassDelta || interfaceDelta;
+
+        template.setAttribute("has_class_signature_delta", hasSignatureDelta);
+
+        template.setAttribute("removed_fields", removedFields);
+        template.setAttribute("added_fields", addedFields);
+        template.setAttribute("changed_fields", changedFields);
+
+        template.setAttribute("removed_annotation_fields",
+                removedAnnotationFields);
+        template.setAttribute("added_annotation_fields", addedAnnotationFields);
+        template.setAttribute("changed_annotation_fields",
+                changedAnnotationFields);
+
+        template.setAttribute("removed_enum_constants", removedEnumConstants);
+        template.setAttribute("added_enum_constants", addedEnumConstants);
+        template.setAttribute("changed_enum_constants", changedEnumConstants);
+
+        template.setAttribute("removed_constructors", removedConstructors);
+        template.setAttribute("added_constructors", addedConstructors);
+        template.setAttribute("changed_constructors", changedConstructors);
+
+        template.setAttribute("removed_methods", removedMethods);
+        template.setAttribute("added_methods", addedMethods);
+        template.setAttribute("changed_methods", changedMethods);
+
+        template.setArgumentContext(commonInfos);
+        b.append(template.toString());
+    }
+}
diff --git a/tools/signature-tools/src/signature/io/html/ExecutableMemberComparator.java b/tools/signature-tools/src/signature/io/html/ExecutableMemberComparator.java
new file mode 100644
index 0000000..e342342
--- /dev/null
+++ b/tools/signature-tools/src/signature/io/html/ExecutableMemberComparator.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.io.html;
+
+import signature.compare.model.IExecutableMemberDelta;
+import signature.model.IArrayType;
+import signature.model.IClassDefinition;
+import signature.model.IClassReference;
+import signature.model.IExecutableMember;
+import signature.model.IParameter;
+import signature.model.IParameterizedType;
+import signature.model.IPrimitiveType;
+import signature.model.ITypeDefinition;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+import signature.model.ITypeVariableReference;
+
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+public class ExecutableMemberComparator implements
+        Comparator<IExecutableMemberDelta<? extends IExecutableMember>> {
+
+    public int compare(IExecutableMemberDelta<? extends IExecutableMember> a,
+            IExecutableMemberDelta<? extends IExecutableMember> b) {
+        assert a.getType() == b.getType();
+        IExecutableMember aMember = null;
+        IExecutableMember bMember = null;
+
+        if (a.getFrom() != null) {
+            aMember = a.getFrom();
+            bMember = b.getFrom();
+        } else {
+            aMember = a.getTo();
+            bMember = b.getTo();
+        }
+
+        int returnValue = aMember.getName().compareTo(bMember.getName());
+        return returnValue != 0 ? returnValue : compareParameterLists(aMember
+                .getParameters(), bMember.getParameters());
+    }
+
+    private int compareParameterLists(List<IParameter> a, List<IParameter> b) {
+        if (a.size() != b.size()) {
+            return a.size() - b.size();
+        }
+        Iterator<IParameter> aIt = a.iterator();
+        Iterator<IParameter> bIt = b.iterator();
+        int returnValue = 0;
+        while (aIt.hasNext() && bIt.hasNext()) {
+            returnValue += getTypeName(aIt.next().getType()).compareTo(
+                    getTypeName(bIt.next().getType()));
+        }
+        return returnValue;
+    }
+
+    private String getTypeName(ITypeReference type) {
+        if (type instanceof IClassReference) {
+            return getTypeName(((IClassReference) type).getClassDefinition());
+        }
+        if (type instanceof ITypeVariableReference) {
+            return getTypeName(((ITypeVariableReference) type)
+                    .getTypeVariableDefinition());
+        }
+        if (type instanceof IParameterizedType) {
+            return getTypeName(((IParameterizedType) type).getRawType());
+        }
+        if (type instanceof IArrayType) {
+            return getTypeName(((IArrayType) type).getComponentType());
+        }
+        if (type instanceof IPrimitiveType) {
+            return ((IPrimitiveType) type).getName();
+        }
+        return type.toString();
+    }
+
+    private String getTypeName(ITypeDefinition type) {
+        if (type instanceof IClassDefinition) {
+            return ((IClassDefinition) type).getName();
+        }
+        if (type instanceof ITypeVariableDefinition) {
+            return ((ITypeVariableDefinition) type).getName();
+        }
+        return type.toString();
+    }
+
+}
diff --git a/tools/signature-tools/src/signature/io/html/FieldByNameComparator.java b/tools/signature-tools/src/signature/io/html/FieldByNameComparator.java
new file mode 100644
index 0000000..9aaf1f8
--- /dev/null
+++ b/tools/signature-tools/src/signature/io/html/FieldByNameComparator.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.io.html;
+
+import java.util.Comparator;
+
+import signature.compare.model.IMemberDelta;
+import signature.model.IField;
+
+public class FieldByNameComparator<T extends IMemberDelta<?>> implements
+        Comparator<T> {
+
+    public int compare(T a, T b) {
+        assert a.getType() == b.getType();
+        IField aField = null;
+        IField bField = null;
+
+        // FIXME File javac or jdt bug.
+        // Note: Casts are required by javac 1.5.0_16.
+        if (a.getFrom() != null) {
+            aField = (IField) a.getFrom();
+            bField = (IField) b.getFrom();
+        } else {
+            aField = (IField) a.getTo();
+            bField = (IField) b.getTo();
+        }
+        return aField.getName().compareTo(bField.getName());
+    }
+}
diff --git a/tools/signature-tools/src/signature/io/html/HtmlDeltaExternalizer.java b/tools/signature-tools/src/signature/io/html/HtmlDeltaExternalizer.java
new file mode 100644
index 0000000..1ba5cba
--- /dev/null
+++ b/tools/signature-tools/src/signature/io/html/HtmlDeltaExternalizer.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.io.html;
+
+import org.antlr.stringtemplate.StringTemplate;
+
+import signature.Version;
+import signature.compare.model.IApiDelta;
+import signature.compare.model.IClassDefinitionDelta;
+import signature.compare.model.IDelta;
+import signature.compare.model.IPackageDelta;
+import signature.compare.model.impl.SigDelta;
+import signature.io.IApiDeltaExternalizer;
+import signature.model.IClassDefinition;
+import signature.model.IPackage;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class HtmlDeltaExternalizer implements IApiDeltaExternalizer {
+
+    private static final String OVERVIEW_PAGE_NAME = "changes.html";
+    private static final String STYLE_SHEET_NAME = "styles.css";
+    private static final String DELTA_FOLDER = "changes" + File.separator;
+
+    public void externalize(String location, IApiDelta apiDelta)
+            throws IOException {
+        if (!location.endsWith(File.separator)) {
+            location += File.separator;
+        }
+
+        File directory = new File(location);
+        if (!directory.exists()) {
+            directory.mkdirs();
+        }
+
+        copyStyleSheet(location);
+
+        Map<String, String> commonInfos = new HashMap<String, String>();
+        commonInfos.put("creation_time", DateFormat.getDateTimeInstance()
+                .format(new Date()));
+        commonInfos.put("from_desc", apiDelta.getFrom().getName());
+        commonInfos.put("to_desc", apiDelta.getTo().getName());
+
+        // write overview page
+        StringBuilder content = new StringBuilder();
+        ApiOverviewPage apiOverviewPage = new ApiOverviewPage(apiDelta,
+                commonInfos);
+        apiOverviewPage.writeTo(content);
+        writeToFile(location + OVERVIEW_PAGE_NAME, content.toString());
+
+        // write package overview
+        Set<IPackageDelta> changedPackages = SigDelta.getChanged(apiDelta
+                .getPackageDeltas());
+        if (!changedPackages.isEmpty()) {
+
+            File file = new File(location + DELTA_FOLDER);
+            if (!file.exists()) {
+                file.mkdir();
+            }
+
+            for (IPackageDelta packageDelta : changedPackages) {
+                content = new StringBuilder();
+                PackageOverviewPage packagePage = new PackageOverviewPage(
+                        packageDelta, commonInfos);
+                packagePage.writeTo(content);
+                IPackage aPackage = getAnElement(packageDelta);
+                String packageOverviewFileName = location + DELTA_FOLDER
+                        + "pkg_" + aPackage.getName() + ".html";
+                writeToFile(packageOverviewFileName, content.toString());
+
+                // write class overviews
+                for (IClassDefinitionDelta classDelta : packageDelta
+                        .getClassDeltas()) {
+                    content = new StringBuilder();
+                    ClassOverviewPage classPage = new ClassOverviewPage(
+                            classDelta, commonInfos);
+                    classPage.writeTo(content);
+                    IClassDefinition aClass = getAnElement(classDelta);
+                    String classOverviewFileName = location + DELTA_FOLDER
+                            + aPackage.getName() + "." + aClass.getName()
+                            + ".html";
+                    writeToFile(classOverviewFileName, content.toString());
+                }
+            }
+        }
+        // write class overview
+    }
+
+    private static <T> T getAnElement(IDelta<T> delta) {
+        if (delta.getFrom() != null) {
+            return delta.getFrom();
+        } else {
+            return delta.getTo();
+        }
+    }
+
+    private void copyStyleSheet(String directory) throws IOException {
+        StringTemplate template = TemplateStore.getStringTemplate("Styles");
+        template.setAttribute("version", Version.VERSION);
+        writeToFile(directory + STYLE_SHEET_NAME, template.toString());
+    }
+
+    private void writeToFile(String fileName, String content)
+            throws IOException {
+        FileOutputStream fileOutputStream = new FileOutputStream(fileName);
+        fileOutputStream.write(content.getBytes());
+        fileOutputStream.flush();
+        fileOutputStream.close();
+    }
+}
diff --git a/tools/signature-tools/src/signature/io/html/IEmitter.java b/tools/signature-tools/src/signature/io/html/IEmitter.java
new file mode 100644
index 0000000..db73e66
--- /dev/null
+++ b/tools/signature-tools/src/signature/io/html/IEmitter.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.io.html;
+
+public interface IEmitter {
+    void writeTo(StringBuilder b);
+}
diff --git a/tools/signature-tools/src/signature/io/html/PackageByNameComparator.java b/tools/signature-tools/src/signature/io/html/PackageByNameComparator.java
new file mode 100644
index 0000000..3bbff71
--- /dev/null
+++ b/tools/signature-tools/src/signature/io/html/PackageByNameComparator.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.io.html;
+
+import signature.compare.model.IPackageDelta;
+import signature.model.IPackage;
+
+import java.util.Comparator;
+
+public class PackageByNameComparator implements Comparator<IPackageDelta> {
+
+    public int compare(IPackageDelta a, IPackageDelta b) {
+        assert a.getType() == b.getType();
+        IPackage aPackage = null;
+        IPackage bPackage = null;
+
+        if (a.getFrom() != null) {
+            aPackage = a.getFrom();
+            bPackage = b.getFrom();
+        } else {
+            aPackage = a.getTo();
+            bPackage = b.getTo();
+        }
+        return aPackage.getName().compareTo(bPackage.getName());
+    }
+}
diff --git a/tools/signature-tools/src/signature/io/html/PackageOverviewPage.java b/tools/signature-tools/src/signature/io/html/PackageOverviewPage.java
new file mode 100644
index 0000000..ccfe3cc
--- /dev/null
+++ b/tools/signature-tools/src/signature/io/html/PackageOverviewPage.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.io.html;
+
+import org.antlr.stringtemplate.StringTemplate;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import signature.compare.model.IClassDefinitionDelta;
+import signature.compare.model.IPackageDelta;
+import signature.compare.model.impl.SigDelta;
+
+public class PackageOverviewPage implements IEmitter {
+
+    private static final String PACGE = "PackageOverviewPage";
+
+    private final IPackageDelta delta;
+
+    private List<IClassDefinitionDelta> removedClasses;
+    private List<IClassDefinitionDelta> addedClasses;
+    private List<IClassDefinitionDelta> changedClasses;
+    private final Map<String, String> commonInfos;
+
+
+    public PackageOverviewPage(IPackageDelta delta,
+            Map<String, String> commonInfos) {
+        this.delta = delta;
+        this.commonInfos = commonInfos;
+        prepareData();
+    }
+
+    private void prepareData() {
+        removedClasses = new ArrayList<IClassDefinitionDelta>(SigDelta
+                .getRemoved(delta.getClassDeltas()));
+        Collections.sort(removedClasses, new ClassByNameComparator());
+
+        addedClasses = new ArrayList<IClassDefinitionDelta>(SigDelta
+                .getAdded(delta.getClassDeltas()));
+        Collections.sort(addedClasses, new ClassByNameComparator());
+
+        changedClasses = new ArrayList<IClassDefinitionDelta>(SigDelta
+                .getChanged(delta.getClassDeltas()));
+        Collections.sort(changedClasses, new ClassByNameComparator());
+    }
+
+    public void writeTo(StringBuilder b) {
+        StringTemplate template = TemplateStore.getStringTemplate(PACGE);
+        template.setArgumentContext(commonInfos);
+        template.setAttribute("package_delta", delta);
+        template.setAttribute("removed_classes", removedClasses);
+        template.setAttribute("added_classes", addedClasses);
+        template.setAttribute("changed_classes", changedClasses);
+        b.append(template.toString());
+    }
+
+
+
+}
diff --git a/tools/signature-tools/src/signature/io/html/TemplateStore.java b/tools/signature-tools/src/signature/io/html/TemplateStore.java
new file mode 100644
index 0000000..a161bf7
--- /dev/null
+++ b/tools/signature-tools/src/signature/io/html/TemplateStore.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.io.html;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.antlr.stringtemplate.StringTemplate;
+import org.antlr.stringtemplate.StringTemplateGroup;
+import org.antlr.stringtemplate.language.DefaultTemplateLexer;
+
+public class TemplateStore {
+
+    private static StringTemplateGroup group = initialize();
+
+
+    private static StringTemplateGroup initialize() {
+        InputStream modelStream = TemplateStore.class.getClassLoader()
+                .getResourceAsStream("model/model.stg");
+        InputStreamReader modelReader = new InputStreamReader(modelStream);
+        StringTemplateGroup modelGroup = new StringTemplateGroup(modelReader,
+                DefaultTemplateLexer.class);
+
+        InputStream stream = TemplateStore.class.getClassLoader()
+                .getResourceAsStream("delta/deltas.stg");
+        InputStreamReader reader = new InputStreamReader(stream);
+        StringTemplateGroup deltaGroup = new StringTemplateGroup(reader,
+                DefaultTemplateLexer.class);
+
+        StringTemplateGroup group = new StringTemplateGroup("signature", null,
+                DefaultTemplateLexer.class);
+        group.setSuperGroup(deltaGroup);
+
+        deltaGroup.setSuperGroup(modelGroup);
+        return group;
+    }
+
+    private TemplateStore() {/* no instances allowed */
+    }
+
+    public static StringTemplate getStringTemplate(String name) {
+        return group.getInstanceOf(name);
+    }
+}
diff --git a/tools/signature-tools/src/signature/io/impl/BinaryApi.java b/tools/signature-tools/src/signature/io/impl/BinaryApi.java
new file mode 100644
index 0000000..f12cf6a7
--- /dev/null
+++ b/tools/signature-tools/src/signature/io/impl/BinaryApi.java
@@ -0,0 +1,83 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * 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 signature.io.impl;

+

+import signature.converter.Visibility;

+import signature.io.IApiExternalizer;

+import signature.io.IApiLoader;

+import signature.model.IApi;

+import java.io.File;

+import java.io.FileInputStream;

+import java.io.FileOutputStream;

+import java.io.IOException;

+import java.io.ObjectInputStream;

+import java.io.ObjectOutputStream;

+import java.util.Set;

+

+public class BinaryApi implements IApiExternalizer, IApiLoader {

+

+    public void externalizeApi(String fileName, IApi api) throws IOException {

+

+        File directory = new File(fileName);

+        if (!directory.exists()) {

+            directory.mkdirs();

+        }

+

+        File file = new File(directory, getFileName(api));

+        file.createNewFile();

+

+        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(

+                file));

+        oos.writeObject(api);

+

+        oos.flush();

+        oos.close();

+    }

+

+    private String getFileName(IApi api) {

+        return api.getName().replaceAll(" ", "_").concat(".sig");

+    }

+

+    public IApi loadApi(String name, Visibility visibility,

+            Set<String> fileNames, Set<String> packageNames) throws

+            IOException {

+        System.err

+                .println("Binary signature loader ignores visibility and " +

+                        "package names.");

+        if (fileNames.size() != 1) {

+            throw new IllegalArgumentException(

+                    "Only one file can be processed by the binary signature " +

+                    "loader.");

+        }

+        String fileName = fileNames.iterator().next();

+        File file = new File(fileName);

+        ObjectInputStream ois = new ObjectInputStream(

+                new FileInputStream(file));

+        IApi sig = null;

+        try {

+            sig = (IApi) ois.readObject();

+        } catch (ClassNotFoundException e) {

+            throw new IllegalArgumentException(e);

+        }

+        if (name != null) {

+            sig.setName(name);

+        }

+

+        ois.close();

+        return sig;

+    }

+}

diff --git a/tools/signature-tools/src/signature/io/impl/ToStringExternalizer.java b/tools/signature-tools/src/signature/io/impl/ToStringExternalizer.java
new file mode 100644
index 0000000..62615af
--- /dev/null
+++ b/tools/signature-tools/src/signature/io/impl/ToStringExternalizer.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.io.impl;
+
+import signature.compare.model.IApiDelta;
+import signature.io.IApiDeltaExternalizer;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+
+public class ToStringExternalizer implements IApiDeltaExternalizer {
+
+    public void externalize(String location, IApiDelta delta)
+            throws IOException {
+
+        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(
+                new FileOutputStream(location));
+
+        if (delta == null) {
+            outputStreamWriter.write("No delta found!");
+        } else {
+            outputStreamWriter.write(delta.toString());
+        }
+        outputStreamWriter.close();
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/IAnnotatableElement.java b/tools/signature-tools/src/signature/model/IAnnotatableElement.java
new file mode 100644
index 0000000..53d6c38
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IAnnotatableElement.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+import java.util.Set;
+
+/**
+ * Common interface for model elements which may be annotated. Annotations can
+ * be attached to:
+ * <ul>
+ * <li>Classes (IClass), including annotations which are also classes
+ * <li>Methods and Constructors (IExecutableMember)
+ * <li>Fields (IField), including the annotation fields and enum constants
+ * <li>Parameters (IParameter)
+ * </ul>
+ */
+public interface IAnnotatableElement {
+
+    /**
+     * Returns a set of annotations of a model element.
+     * 
+     * @return a set of annotations of a model element
+     */
+    Set<IAnnotation> getAnnotations();
+}
diff --git a/tools/signature-tools/src/signature/model/IAnnotation.java b/tools/signature-tools/src/signature/model/IAnnotation.java
new file mode 100644
index 0000000..c31689d
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IAnnotation.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+import java.util.Set;
+
+/**
+ * {@code IAnnotation} models an <em>instance</em> of an annotation which is
+ * attached to a program element. The definition of an annotation type is
+ * modeled as an {@link IClassDefinition} with the {@link Kind#ANNOTATION}.
+ */
+public interface IAnnotation {
+    /**
+     * Returns the annotation type of this annotation.
+     * 
+     * @return the annotation type of this annotation
+     */
+    IClassReference getType();
+
+    /**
+     * Returns the elements declared in this annotation. The values which are
+     * not declared are not contained in this list. Each element consists of its
+     * name and its value.
+     * 
+     * @return elements declared in this annotation
+     */
+    Set<IAnnotationElement> getElements();
+}
diff --git a/tools/signature-tools/src/signature/model/IAnnotationElement.java b/tools/signature-tools/src/signature/model/IAnnotationElement.java
new file mode 100644
index 0000000..5637fd6
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IAnnotationElement.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+/**
+ * {@code IAnnotationElement} models an annotation element which consist of a
+ * name and a value.
+ */
+public interface IAnnotationElement {
+    /**
+     * Returns the value of this annotation element. The type of this value is
+     * restricted to the possible value types for annotation elements.
+     * <p>
+     * The following types are possible:
+     * <ul>
+     * <li>a wrapper class for a primitive type
+     * <li>String (for String values)
+     * <li>IType (representing a class literal) FIXME Reference? Def?
+     * <li>IEnumConstant (representing an enum constant)
+     * <li>IAnnotation
+     * </ul>
+     * and (one-dimensional) arrays of the above types.
+     * 
+     * @return the value of this annotation element
+     */
+    Object getValue();
+
+    /**
+     * Returns the corresponding annotation field declaration. This declaration
+     * contains e.g. the name of this element, its type and its modifiers. The
+     * declaration also contains the default value of this element which is
+     * overwritten by this annotation element.
+     * 
+     * @return the corresponding annotation field declaration
+     */
+    IAnnotationField getDeclaringField();
+
+}
diff --git a/tools/signature-tools/src/signature/model/IAnnotationField.java b/tools/signature-tools/src/signature/model/IAnnotationField.java
new file mode 100644
index 0000000..c40707f
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IAnnotationField.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+/**
+ * {@code IAnnotationField} models a field in a annotation definition. The
+ * following example shows an annotation field <code>androField</code> of type
+ * String and the default value "droid".
+ * 
+ * <pre>
+ * 
+ * @interface A { String androField() default "droid"; }
+ * 
+ *            </pre>
+ */
+public interface IAnnotationField extends IField {
+
+    /**
+     * Returns the default value. If no default value is set then null is
+     * returned.
+     * 
+     * The type of the returned object is one of the following:
+     * <ul>
+     * <li>a wrapper class for a primitive type
+     * <li>String (for String values)
+     * <li>IType (representing a class literal)
+     * <li>IEnumConstant (representing an enum constant)
+     * <li>IAnnotation
+     * </ul>
+     * and (one-dimensional) arrays of the above types. If an array is returned,
+     * then the type of the result is Object[]. The elements of this array are
+     * of the above listed types.
+     */
+    Object getDefaultValue();
+}
diff --git a/tools/signature-tools/src/signature/model/IApi.java b/tools/signature-tools/src/signature/model/IApi.java
new file mode 100644
index 0000000..de51938
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IApi.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+import signature.converter.Visibility;
+
+import java.util.Set;
+
+/**
+ * {@code IApi} models the root of an api.
+ */
+public interface IApi {
+    /**
+     * Returns the name of this api.
+     * 
+     * @return the name of this api
+     */
+    String getName();
+
+    /**
+     * Sets the name of this api.
+     * 
+     * @param name
+     *            the name of this api
+     */
+    void setName(String name);
+
+    /**
+     * Returns the set of packages which constitute this api.
+     * 
+     * @return the set of packages which constitute this api
+     */
+    Set<IPackage> getPackages();
+
+    /**
+     * Returns the visibility of this api. The visibility describes which
+     * elements are visible. Only elements with a visibility greater or equal
+     * this visibility are contained in this api model.
+     * 
+     * @return the visibility of this api
+     * @see Visibility
+     */
+    Visibility getVisibility();
+}
diff --git a/tools/signature-tools/src/signature/model/IArrayType.java b/tools/signature-tools/src/signature/model/IArrayType.java
new file mode 100644
index 0000000..bb63e67
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IArrayType.java
@@ -0,0 +1,30 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * 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 signature.model;

+

+/**

+ * {@code IArrayType} models an array type.

+ */

+public interface IArrayType extends ITypeReference {

+

+    /**

+     * Returns the component type of this array type.

+     * 

+     * @return component type of this array type

+     */

+    ITypeReference getComponentType();

+}

diff --git a/tools/signature-tools/src/signature/model/IClassDefinition.java b/tools/signature-tools/src/signature/model/IClassDefinition.java
new file mode 100644
index 0000000..1bd5401
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IClassDefinition.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * {@code IClassDefinition} models a class definition. This is the model
+ * equivalent to a class.
+ */
+public interface IClassDefinition extends ITypeDefinition, IGenericDeclaration,
+        IAnnotatableElement {
+
+    /**
+     * Returns the kind of this class definition.
+     * 
+     * @return the kind of this class definition
+     */
+    Kind getKind();
+
+    /**
+     * Returns the name of this class definition.
+     * 
+     * @return the name of this class definition
+     */
+    String getName();
+
+    /**
+     * Returns the '.' separated package name of this class.
+     * 
+     * @return the '.' separated package name of this class
+     */
+    String getPackageName();
+
+    /**
+     * Returns a list containing each package fragment.
+     * <p>
+     * If {@link #getPackageName()} returns : "a.b.c" this method returns a list
+     * containing the three elements "a", "b", "c".
+     * <p>
+     * Note: this method exists only for convenience in output templating.
+     * 
+     * @return a list containing each package fragment
+     */
+    List<String> getPackageFragments();
+
+    /**
+     * Returns the qualified name of this class definition. The qualified name
+     * is composed of {@link #getPackageName()} '.' {@link #getName()}
+     * 
+     * @return the qualified name of this class definition
+     */
+    String getQualifiedName();
+
+    /**
+     * Returns the super class for this class definition. May return {@code
+     * null} if this class definition does not have any superclass. This is the
+     * case if the kind of this class definition is {@link Kind#INTERFACE} or
+     * this class definition is {@link Object}.
+     * 
+     * @return the super class for this class definition or {@code null}
+     */
+    ITypeReference getSuperClass();
+
+    /**
+     * Returns the declared interfaces this class definition implements . If no
+     * interfaces are declared, an empty set is returned.
+     * 
+     * @return the declared interfaces for this class definition
+     */
+    Set<ITypeReference> getInterfaces();
+
+    /**
+     * Returns the modifiers for this class definition.
+     * 
+     * @return the modifiers for this class definition
+     */
+    Set<Modifier> getModifiers();
+
+    /**
+     * Returns all declared methods of this class definition.
+     * 
+     * @return all declared methods of this class definition
+     */
+    Set<IMethod> getMethods();
+
+    /**
+     * Returns all declared constructors of this class definition.
+     * 
+     * @return all declared constructors of this class definition
+     */
+    Set<IConstructor> getConstructors();
+
+    /**
+     * Returns all declared fields of this class definition.
+     * 
+     * @return all declared fields of this class definition
+     */
+    Set<IField> getFields();
+
+    /**
+     * Returns all declared enumeration constant definitions of this class
+     * definition. The returned set may only contain elements if the kind of
+     * this class definition is {@link Kind#ENUM}.
+     * 
+     * @return all declared enumeration constants of this class definition
+     */
+    Set<IEnumConstant> getEnumConstants();
+
+    /**
+     * Returns all declared annotation field definitions of this class
+     * definition. The returned set may only contain elements if the kind of
+     * this class definition is {@link Kind#ANNOTATION}.
+     * 
+     * @return all declared annotation fields of this class definition
+     */
+    Set<IAnnotationField> getAnnotationFields();
+
+    /**
+     * Returns all classes which where defined in the lexical scope of this
+     * class definition. Anonymous classes are never returned.
+     * 
+     * @return all classes which where defined in the lexical scope of this
+     *         class definition
+     */
+    Set<IClassDefinition> getInnerClasses();
+}
diff --git a/tools/signature-tools/src/signature/model/IClassReference.java b/tools/signature-tools/src/signature/model/IClassReference.java
new file mode 100644
index 0000000..bcb2c55
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IClassReference.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+/**
+ * {@code IClassReference} models a reference to an {@link IClassDefinition}. If
+ * the referenced {@link IClassDefinition} defines
+ * {@link ITypeVariableDefinition}s, this reference can be seen as a raw type.
+ */
+public interface IClassReference extends ITypeReference {
+
+    /**
+     * Returns the definition this class reference is referencing.
+     * 
+     * @return the definition this class reference is referencing
+     */
+    IClassDefinition getClassDefinition();
+}
diff --git a/tools/signature-tools/src/signature/model/IConstructor.java b/tools/signature-tools/src/signature/model/IConstructor.java
new file mode 100644
index 0000000..29f5275
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IConstructor.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+/**
+ * {@code IConstructor} models a constructor.
+ */
+public interface IConstructor extends IExecutableMember {
+}
diff --git a/tools/signature-tools/src/signature/model/IEnumConstant.java b/tools/signature-tools/src/signature/model/IEnumConstant.java
new file mode 100644
index 0000000..681e62b
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IEnumConstant.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+/**
+ * {@code IEnumConstant} models an enumeration constant.
+ */
+public interface IEnumConstant extends IField {
+
+    /**
+     * Returns the ordinal of this enum constant.
+     * 
+     * @return the ordinal of this enum constant.
+     */
+    int getOrdinal();
+}
diff --git a/tools/signature-tools/src/signature/model/IExecutableMember.java b/tools/signature-tools/src/signature/model/IExecutableMember.java
new file mode 100644
index 0000000..ef7f7ba
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IExecutableMember.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * {@code IExecutableMember} is the common super interface for methods an
+ * constructors.
+ */
+public interface IExecutableMember extends IGenericDeclaration,
+        IAnnotatableElement {
+
+    /**
+     * Returns the name of this executable member.
+     * 
+     * @return the name of this executable member
+     */
+    String getName();
+
+    /**
+     * Returns the parameters of this executable member.
+     * 
+     * @return the parameters of this executable member
+     */
+    List<IParameter> getParameters();
+
+    /**
+     * Returns the declared exceptions of this executable member.
+     * 
+     * @return the declared exceptions of this executable member
+     */
+    Set<ITypeReference> getExceptions();
+
+    /**
+     * Returns the modifiers of this executable member.
+     * 
+     * @return the modifiers of this executable member
+     */
+    Set<Modifier> getModifiers();
+}
diff --git a/tools/signature-tools/src/signature/model/IField.java b/tools/signature-tools/src/signature/model/IField.java
new file mode 100644
index 0000000..3cf7593
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IField.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+import java.util.Set;
+
+/**
+ * {@code IField} models a field.
+ */
+public interface IField extends IAnnotatableElement {
+
+    /**
+     * Returns the name of this field.
+     * 
+     * @return the name of this field
+     */
+    String getName();
+
+    /**
+     * Returns the type of this field.
+     * 
+     * @return the type of this field
+     */
+    ITypeReference getType();
+
+    /**
+     * Returns the modifiers of this field.
+     * 
+     * @return the modifiers of this field
+     */
+    Set<Modifier> getModifiers();
+}
diff --git a/tools/signature-tools/src/signature/model/IGenericDeclaration.java b/tools/signature-tools/src/signature/model/IGenericDeclaration.java
new file mode 100644
index 0000000..d7f4683
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IGenericDeclaration.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+import java.util.List;
+
+/**
+ * {@code IGenericDeclaration} is the common base interface for elements which
+ * can define type variables.
+ */
+public interface IGenericDeclaration {
+
+    /**
+     * Returns a list of all defined type variables on this generic declaration.
+     * 
+     * @return a list of all defined type variables
+     */
+    List<ITypeVariableDefinition> getTypeParameters();
+
+    /**
+     * Returns the class definition which declares this element or {@code null}
+     * if this declaration is a top level class definition.
+     * 
+     * @return the class definition which declares this element or {@code null}
+     */
+    IClassDefinition getDeclaringClass();
+}
diff --git a/tools/signature-tools/src/signature/model/IMethod.java b/tools/signature-tools/src/signature/model/IMethod.java
new file mode 100644
index 0000000..e205db1
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IMethod.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+import signature.model.impl.SigPrimitiveType;
+
+/**
+ * {@code IMethod} models a method.
+ */
+public interface IMethod extends IExecutableMember {
+
+    /**
+     * Returns the return type of this method.
+     * <p>
+     * If the declared return type is {@code void}
+     * {@link SigPrimitiveType#VOID_TYPE} is returned.
+     * 
+     * @return the return type of this method
+     */
+    ITypeReference getReturnType();
+}
diff --git a/tools/signature-tools/src/signature/model/IPackage.java b/tools/signature-tools/src/signature/model/IPackage.java
new file mode 100644
index 0000000..78b14ce
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IPackage.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * {@code IPackage} models a package.
+ */
+public interface IPackage extends IAnnotatableElement {
+
+    /**
+     * Returns the name of this package.
+     * 
+     * @return the name of this package
+     */
+    String getName();
+
+    /**
+     * Returns a list containing each package fragment.
+     * <p>
+     * If {@link #getName()} returns : "a.b.c" this method returns a list
+     * containing the three elements "a", "b", "c".
+     * <p>
+     * Note: this method exists only for convenience in output templating.
+     * 
+     * @return a list containing each package fragment
+     */
+    List<String> getPackageFragments();
+
+    /**
+     * Returns all classes declared in this package, including ordinary classes,
+     * interfaces, enum types and annotation types. Nested classes are returned
+     * as well.
+     * 
+     * @return all classes declared in this package
+     */
+    Set<IClassDefinition> getClasses();
+}
diff --git a/tools/signature-tools/src/signature/model/IParameter.java b/tools/signature-tools/src/signature/model/IParameter.java
new file mode 100644
index 0000000..bd359d5
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IParameter.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+/**
+ * {@code IParameter} models a parameter of an {@link IExecutableMember}.
+ */
+public interface IParameter extends IAnnotatableElement {
+
+    /**
+     * Returns the type of this parameter.
+     * 
+     * @return the type of this parameter
+     */
+    ITypeReference getType();
+}
diff --git a/tools/signature-tools/src/signature/model/IParameterizedType.java b/tools/signature-tools/src/signature/model/IParameterizedType.java
new file mode 100644
index 0000000..59f5692
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IParameterizedType.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+import java.util.List;
+
+/**
+ * {@code IParameterizedType} models a parameterized type. A parameterized type
+ * instantiates a generic class definition with actual type arguments.
+ * 
+ * <pre>
+ * IClassDefinition:
+ * public class A<T> {}
+ *
+ * public class XXX {
+ * IParameterizedType (raw type: A , type arguments: Number)
+ *   public A<Number> fields;
+ * }
+ * </pre>
+ */
+public interface IParameterizedType extends ITypeReference {
+
+    /**
+     * Returns the actual type arguments of this parameterized type.
+     * 
+     * @return the actual type arguments of this parameterized type
+     */
+    List<ITypeReference> getTypeArguments();
+
+    /**
+     * Returns the raw type of this parameterized type.
+     * 
+     * @return the raw type of this parameterized type
+     */
+    IClassReference getRawType();
+
+    /**
+     * Returns the owner type of this parameterized type or {@code null}.
+     * 
+     * <pre>
+     * class Y&lt;T&gt; {
+     *     class Z&lt;S&gt; {
+     *     }
+     *
+     *     Y&lt;Integer&gt;.Z&lt;String&gt; a;
+     * }
+     * </pre>
+     */
+    ITypeReference getOwnerType(); // A.B<String> -> A
+}
diff --git a/tools/signature-tools/src/signature/model/IPrimitiveType.java b/tools/signature-tools/src/signature/model/IPrimitiveType.java
new file mode 100644
index 0000000..917b96b
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IPrimitiveType.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+/**
+ * {@code IPrimitiveType} models a primitive type.
+ */
+public interface IPrimitiveType extends ITypeReference {
+
+    /**
+     * Returns the name of this primitive type, i.e. one of the following
+     * strings:
+     * <ul>
+     * <li><code>boolean</code>
+     * <li><code>byte</code>
+     * <li><code>char</code>
+     * <li><code>short</code>
+     * <li><code>int</code>
+     * <li><code>float</code>
+     * <li><code>double</code>
+     * <li><code>void</code>
+     * </ul>
+     * 
+     * @return the name of this primitive type
+     */
+    public String getName();
+}
diff --git a/tools/signature-tools/src/signature/model/ITypeDefinition.java b/tools/signature-tools/src/signature/model/ITypeDefinition.java
new file mode 100644
index 0000000..b182f21
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/ITypeDefinition.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+/**
+ * {@code ITypeDefinition} is the common interface for type definitions. A type
+ * definition is either an {@link ITypeVariableDefinition} or an
+ * {@link IClassDefinition}.
+ */
+public interface ITypeDefinition {
+}
diff --git a/tools/signature-tools/src/signature/model/ITypeReference.java b/tools/signature-tools/src/signature/model/ITypeReference.java
new file mode 100644
index 0000000..f17f172
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/ITypeReference.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+/**
+ * {@code ITypeReference} is the common interface for type references.
+ */
+public interface ITypeReference {
+}
diff --git a/tools/signature-tools/src/signature/model/ITypeVariableDefinition.java b/tools/signature-tools/src/signature/model/ITypeVariableDefinition.java
new file mode 100644
index 0000000..df0ead0
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/ITypeVariableDefinition.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+import java.util.List;
+
+/**
+ * {@code ITypeVariableDefinition} models a type variable definition.
+ */
+public interface ITypeVariableDefinition extends ITypeDefinition {
+
+    /**
+     * Returns the upper bounds for this type variable as specified by the
+     * extends clause. If no upper bounds are explicitly specified then
+     * java.lang.Object is returned as upper bound.
+     * 
+     * @return the upper bounds for this type variable
+     */
+    List<ITypeReference> getUpperBounds();
+
+    /**
+     * Returns the name of this type variable.
+     * 
+     * @return the name of this type variable
+     */
+    String getName();
+
+    /**
+     * Returns the element on which this type variable is declared.
+     * 
+     * @return the element on which this type variable is declared
+     */
+    IGenericDeclaration getGenericDeclaration();
+}
diff --git a/tools/signature-tools/src/signature/model/ITypeVariableReference.java b/tools/signature-tools/src/signature/model/ITypeVariableReference.java
new file mode 100644
index 0000000..64e0657
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/ITypeVariableReference.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+/**
+ * {@code ITypeVariableReference} models a reference to an
+ * {@link ITypeVariableDefinition}.
+ */
+public interface ITypeVariableReference extends ITypeReference {
+
+    /**
+     * Returns the definition this type variable reference is referencing.
+     * 
+     * @return the definition this type variable reference is referencing
+     */
+    ITypeVariableDefinition getTypeVariableDefinition();
+}
diff --git a/tools/signature-tools/src/signature/model/IWildcardType.java b/tools/signature-tools/src/signature/model/IWildcardType.java
new file mode 100644
index 0000000..02a0d2d
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/IWildcardType.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+import java.util.List;
+
+/**
+ * {@code IWildcardType} models a wildcard type.
+ */
+public interface IWildcardType extends ITypeReference {
+
+    /**
+     * Returns the upper bounds for this type variable as specified by the
+     * extends clause. If no upper bounds are explicitly specified then
+     * java.lang.Object is returned as upper bound.
+     * 
+     * @return the upper bounds for this type variable
+     */
+    List<ITypeReference> getUpperBounds();
+
+    /**
+     * Returns the lower bounds for this type variable as specified by the super
+     * clause. If no lower bounds are explicitly specified then null is returned
+     * as lower bound.
+     * 
+     * @return the lower bounds for this type variable
+     */
+    ITypeReference getLowerBound();
+
+}
diff --git a/tools/signature-tools/src/signature/model/Kind.java b/tools/signature-tools/src/signature/model/Kind.java
new file mode 100644
index 0000000..219e039
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/Kind.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+/**
+ * Type of the modeled class.
+ */
+public enum Kind {
+    CLASS("class"), INTERFACE("interface"), ANNOTATION("@interface"), ENUM(
+            "enum"), UNINITIALIZED("UNINITIALIZED");
+
+    private final String name;
+
+    Kind(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/Modifier.java b/tools/signature-tools/src/signature/model/Modifier.java
new file mode 100644
index 0000000..223e88f
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/Modifier.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model;
+
+import java.util.Set;
+
+/**
+ * {@class Modifier} models a modifer.
+ */
+public enum Modifier {
+    PUBLIC("public"), PRIVATE("private"), PROTECTED("protected"), STATIC(
+            "static"), FINAL("final"), SYNCHRONIZED("synchronized"), VOLATILE(
+            "volatile"), TRANSIENT("transient"), NATIVE("native"), ABSTRACT(
+            "abstract"), STRICT("strict");
+
+    private final String printableName;
+
+    private Modifier(String printableName) {
+        this.printableName = printableName;
+    }
+
+    @Override
+    public String toString() {
+        return printableName;
+    }
+
+    public static String toString(Set<Modifier> modifiers) {
+        StringBuilder s = new StringBuilder();
+
+        for (Modifier modifier : values()) {
+            if (modifiers.contains(modifier)) {
+                s.append(modifier.printableName);
+                s.append(" ");
+            }
+        }
+
+        return s.toString();
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigAnnotatableElement.java b/tools/signature-tools/src/signature/model/impl/SigAnnotatableElement.java
new file mode 100644
index 0000000..53f021e
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigAnnotatableElement.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Set;
+
+import signature.model.IAnnotatableElement;
+import signature.model.IAnnotation;
+
+@SuppressWarnings("serial")
+public abstract class SigAnnotatableElement implements IAnnotatableElement,
+        Serializable {
+    private Set<IAnnotation> annotations;
+
+    public SigAnnotatableElement() {
+        annotations = Collections.emptySet();
+    }
+
+    public Set<IAnnotation> getAnnotations() {
+        return annotations;
+    }
+
+    public void setAnnotations(Set<IAnnotation> annotations) {
+        this.annotations = annotations;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        for (IAnnotation annotation : getAnnotations()) {
+            builder.append(annotation);
+        }
+        return builder.toString();
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigAnnotation.java b/tools/signature-tools/src/signature/model/impl/SigAnnotation.java
new file mode 100644
index 0000000..b7d0354
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigAnnotation.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import signature.model.IAnnotation;
+import signature.model.IAnnotationElement;
+import signature.model.IClassReference;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Set;
+
+@SuppressWarnings("serial")
+public class SigAnnotation implements IAnnotation, Serializable {
+
+    private Set<IAnnotationElement> elements;
+    private IClassReference type;
+
+    public SigAnnotation() {
+        elements = Collections.emptySet();
+    }
+
+    public IClassReference getType() {
+        return type;
+    }
+
+    public void setType(IClassReference type) {
+        this.type = type;
+    }
+
+    public Set<IAnnotationElement> getElements() {
+        return elements;
+    }
+
+    public void setElements(Set<IAnnotationElement> elements) {
+        this.elements = elements;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("@");
+        builder.append(getType());
+        if (!getElements().isEmpty()) {
+            builder.append("{");
+            for (IAnnotationElement element : getElements()) {
+                builder.append("\n");
+                builder.append(element.toString());
+            }
+            builder.append("}");
+        }
+        return builder.toString();
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigAnnotationElement.java b/tools/signature-tools/src/signature/model/impl/SigAnnotationElement.java
new file mode 100644
index 0000000..3d676a7
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigAnnotationElement.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import java.io.Serializable;
+
+import signature.model.IAnnotationElement;
+import signature.model.IAnnotationField;
+
+@SuppressWarnings("serial")
+public class SigAnnotationElement implements IAnnotationElement, Serializable {
+
+    private IAnnotationField declaringField;
+    private Object value;
+
+    public IAnnotationField getDeclaringField() {
+        return declaringField;
+    }
+
+    public void setDeclaringField(IAnnotationField declaringField) {
+        this.declaringField = declaringField;
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    public void setValue(Object value) {
+        this.value = value;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append(getDeclaringField().getName());
+        builder.append(" = ");
+        builder.append(getValue());
+        return builder.toString();
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigAnnotationField.java b/tools/signature-tools/src/signature/model/impl/SigAnnotationField.java
new file mode 100644
index 0000000..5dd6faf
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigAnnotationField.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import java.io.Serializable;
+
+import signature.model.IAnnotationField;
+
+@SuppressWarnings("serial")
+public class SigAnnotationField extends SigField implements IAnnotationField,
+        Serializable {
+
+    private Object defaultValue = Uninitialized.unset();
+
+    public SigAnnotationField(String name) {
+        super(name);
+    }
+
+    public Object getDefaultValue() {
+        return defaultValue;
+    }
+
+    public void setDefaultValue(Object defaultValue) {
+        this.defaultValue = defaultValue;
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigApi.java b/tools/signature-tools/src/signature/model/impl/SigApi.java
new file mode 100644
index 0000000..b573f8f
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigApi.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import java.io.Serializable;
+import java.util.Set;
+
+import signature.converter.Visibility;
+import signature.model.IApi;
+import signature.model.IPackage;
+
+@SuppressWarnings("serial")
+public class SigApi implements IApi, Serializable {
+
+    private Set<IPackage> packages = Uninitialized.unset();
+    private String description;
+    private Visibility visibility;
+
+    public SigApi(String description, Visibility visibility) {
+        this.description = description;
+        this.visibility = visibility;
+    }
+
+    public String getName() {
+        return description;
+    }
+
+    public void setName(String description) {
+        this.description = description;
+    }
+
+    public Set<IPackage> getPackages() {
+        return packages;
+    }
+
+    public void setPackages(Set<IPackage> packages) {
+        this.packages = packages;
+    }
+
+    public Visibility getVisibility() {
+        return visibility;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append(getName());
+        return builder.toString();
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigArrayType.java b/tools/signature-tools/src/signature/model/impl/SigArrayType.java
new file mode 100644
index 0000000..3d20824
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigArrayType.java
@@ -0,0 +1,69 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * 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 signature.model.impl;

+

+import java.io.Serializable;

+

+import signature.model.IArrayType;

+import signature.model.ITypeReference;

+

+@SuppressWarnings("serial")

+public class SigArrayType implements IArrayType, Serializable {

+    private ITypeReference componentType;

+

+    public SigArrayType(ITypeReference componentType) {

+        this.componentType = componentType;

+    }

+

+    public ITypeReference getComponentType() {

+        return componentType;

+    }

+

+    @Override

+    public int hashCode() {

+        return SigArrayType.hashCode(this);

+    }

+

+    public static int hashCode(IArrayType type) {

+        return type.getComponentType().hashCode();

+    }

+

+    @Override

+    public boolean equals(Object obj) {

+        return SigArrayType.equals(this, obj);

+    }

+

+    public static boolean equals(IArrayType thiz, Object that) {

+        if (!(that instanceof IArrayType)) {

+            return false;

+        }

+        IArrayType other = (IArrayType) that;

+        return thiz.getComponentType().equals(other.getComponentType());

+    }

+

+    @Override

+    public String toString() {

+        return SigArrayType.toString(this);

+    }

+

+    public static String toString(IArrayType type) {

+        StringBuilder builder = new StringBuilder();

+        builder.append(type.getComponentType().toString());

+        builder.append("[]");

+        return builder.toString();

+    }

+}

diff --git a/tools/signature-tools/src/signature/model/impl/SigClassDefinition.java b/tools/signature-tools/src/signature/model/impl/SigClassDefinition.java
new file mode 100644
index 0000000..fe7c7ab
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigClassDefinition.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+import signature.model.IAnnotationField;
+import signature.model.IClassDefinition;
+import signature.model.IConstructor;
+import signature.model.IEnumConstant;
+import signature.model.IField;
+import signature.model.IMethod;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+import signature.model.Kind;
+import signature.model.Modifier;
+import signature.model.util.ModelUtil;
+
+@SuppressWarnings("serial")
+public class SigClassDefinition extends SigAnnotatableElement implements
+        IClassDefinition, Serializable {
+
+    private String name;
+    private Kind kind = Kind.UNINITIALIZED;
+    private ITypeReference superClass = Uninitialized.unset();
+    private Set<ITypeReference> interfaces = Uninitialized.unset();
+    private Set<Modifier> modifiers = Uninitialized.unset();
+    private Set<IMethod> methods = Uninitialized.unset();
+    private Set<IConstructor> constructors = Uninitialized.unset();
+    private Set<IClassDefinition> innerClasses = Uninitialized.unset();
+    private Set<IAnnotationField> annotationFields = Uninitialized.unset();
+    private Set<IField> fields = Uninitialized.unset();
+    private Set<IEnumConstant> enumConstants = Uninitialized.unset();
+    private IClassDefinition declaringClass = Uninitialized.unset();
+    private List<ITypeVariableDefinition> typeParameters = Uninitialized
+            .unset();
+    private String packageName;
+
+    public SigClassDefinition(String packageName, String name) {
+        this.packageName = packageName;
+        this.name = name;
+    }
+
+    public Kind getKind() {
+        return kind;
+    }
+
+    public void setKind(Kind kind) {
+        this.kind = kind;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getPackageName() {
+        return packageName;
+    }
+
+    public List<String> getPackageFragments() {
+        return Arrays.asList(packageName.split("\\."));
+    }
+
+    public String getQualifiedName() {
+        return packageName + "." + name;
+    }
+
+    public Set<Modifier> getModifiers() {
+        return modifiers;
+    }
+
+    public void setModifiers(Set<Modifier> modifiers) {
+        this.modifiers = modifiers;
+    }
+
+    public Set<IClassDefinition> getInnerClasses() {
+        return innerClasses;
+    }
+
+    public void setInnerClasses(Set<IClassDefinition> innerClasses) {
+        this.innerClasses = innerClasses;
+    }
+
+    public Set<ITypeReference> getInterfaces() {
+        return interfaces;
+    }
+
+    public void setInterfaces(Set<ITypeReference> interfaces) {
+        this.interfaces = interfaces;
+    }
+
+    public Set<IMethod> getMethods() {
+        return methods;
+    }
+
+    public void setMethods(Set<IMethod> methods) {
+        this.methods = methods;
+    }
+
+    public Set<IConstructor> getConstructors() {
+        return constructors;
+    }
+
+    public void setConstructors(Set<IConstructor> constructors) {
+        this.constructors = constructors;
+    }
+
+    public ITypeReference getSuperClass() {
+        return superClass;
+    }
+
+    public void setSuperClass(ITypeReference superClass) {
+        this.superClass = superClass;
+    }
+
+    public IClassDefinition getDeclaringClass() {
+        return declaringClass;
+    }
+
+    public void setDeclaringClass(IClassDefinition declaringClass) {
+        this.declaringClass = declaringClass;
+    }
+
+    public Set<IAnnotationField> getAnnotationFields() {
+        return annotationFields;
+    }
+
+    public void setAnnotationFields(Set<IAnnotationField> annotationFields) {
+        this.annotationFields = annotationFields;
+    }
+
+    public Set<IField> getFields() {
+        return fields;
+    }
+
+    public void setFields(Set<IField> fields) {
+        this.fields = fields;
+    }
+
+    public Set<IEnumConstant> getEnumConstants() {
+        return enumConstants;
+    }
+
+    public void setEnumConstants(Set<IEnumConstant> enumConstants) {
+        this.enumConstants = enumConstants;
+    }
+
+    public List<ITypeVariableDefinition> getTypeParameters() {
+        return typeParameters;
+    }
+
+    public void setTypeParameters(
+            List<ITypeVariableDefinition> typeParameters) {
+        this.typeParameters = typeParameters;
+    }
+
+    @Override
+    public int hashCode() {
+        return SigClassDefinition.hashCode(this);
+    }
+
+    public static int hashCode(IClassDefinition definition) {
+        // FIXME find out why name and packageName are null during
+        // de-serialization some cases
+        // replace the following lines with:
+        // return definition.getQualifiedName().hashCode();
+        final int prime = 31;
+        int result = 1;
+        result = prime
+                + ((definition.getName() == null) ? 0 : definition.getName()
+                        .hashCode());
+        result = prime
+                * result
+                + ((definition.getPackageName() == null) ? 0 : definition
+                        .getPackageName().hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return SigClassDefinition.equals(this, obj);
+    }
+
+    public static boolean equals(IClassDefinition thiz, Object obj) {
+        if (thiz == obj) return true;
+        if (obj instanceof IClassDefinition) {
+            IClassDefinition that = (IClassDefinition) obj;
+            return thiz.getName().equals(that.getName())
+                    && thiz.getPackageName().equals(that.getPackageName());
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return SigClassDefinition.toString(this);
+    }
+
+    public static String toString(IClassDefinition type) {
+        StringBuilder builder = new StringBuilder();
+        if (type.getAnnotations() != null && !type.getAnnotations().isEmpty()) {
+            // FIXME print annotations builder.append(super.toString());
+            builder.append("\n");
+        }
+        builder.append(type.getQualifiedName());
+        if (type.getTypeParameters() != null
+                && (!type.getTypeParameters().isEmpty())) {
+            builder.append("<");
+            ModelUtil.separate(type.getTypeParameters(), ", ");
+            builder.append(">");
+        }
+        return builder.toString();
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigClassReference.java b/tools/signature-tools/src/signature/model/impl/SigClassReference.java
new file mode 100644
index 0000000..d4336de
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigClassReference.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import signature.model.IClassDefinition;
+import signature.model.IClassReference;
+
+import java.io.Serializable;
+
+@SuppressWarnings("serial")
+public class SigClassReference implements IClassReference, Serializable {
+
+    private final IClassDefinition definition;
+
+    public SigClassReference(IClassDefinition definition) {
+        this.definition = definition;
+    }
+
+    public IClassDefinition getClassDefinition() {
+        return definition;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return SigClassReference.equals(this, obj);
+    }
+
+    public static boolean equals(IClassReference thiz, Object that) {
+        if (that instanceof IClassReference) {
+            return thiz.getClassDefinition().equals(
+                    ((IClassReference) that).getClassDefinition());
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return SigClassReference.hashCode(this);
+    }
+
+    public static int hashCode(IClassReference thiz) {
+        return thiz.getClassDefinition().hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return SigClassReference.toString(this);
+    }
+
+    public static String toString(IClassReference thiz) {
+        return "-> " + thiz.getClassDefinition().getQualifiedName();
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigConstructor.java b/tools/signature-tools/src/signature/model/impl/SigConstructor.java
new file mode 100644
index 0000000..1da3026
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigConstructor.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import java.io.Serializable;
+
+import signature.model.IConstructor;
+import signature.model.Modifier;
+import signature.model.util.ModelUtil;
+
+@SuppressWarnings("serial")
+public class SigConstructor extends SigExecutableMember implements
+        IConstructor, Serializable {
+
+    public SigConstructor(String name) {
+        super(name);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append(super.toString());
+        builder.append(" ");
+        builder.append(Modifier.toString(getModifiers()));
+        if (getTypeParameters() != null && !getTypeParameters().isEmpty()) {
+            builder.append("<");
+            builder.append(ModelUtil.separate(getTypeParameters(), ", "));
+            builder.append("> ");
+        }
+        builder.append(getName());
+        builder.append("(");
+        builder.append(getParameters().isEmpty() ? "" : ModelUtil.separate(
+                getParameters(), ", "));
+        builder.append(")");
+        if (getExceptions() != null && !getExceptions().isEmpty()) {
+            builder.append(" throws ");
+            builder.append(ModelUtil.separate(getExceptions(), " "));
+        }
+        return builder.toString();
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigEnumConstant.java b/tools/signature-tools/src/signature/model/impl/SigEnumConstant.java
new file mode 100644
index 0000000..2878988
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigEnumConstant.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import signature.model.IEnumConstant;
+
+@SuppressWarnings("serial")
+public class SigEnumConstant extends SigField implements IEnumConstant {
+
+    private static final int UNKNOWN = -1;
+
+    private int ordinal = UNKNOWN;
+
+    public SigEnumConstant(String name) {
+        super(name);
+    }
+
+    public int getOrdinal() {
+        if (ordinal == UNKNOWN) {
+            throw new UnsupportedOperationException();
+        }
+        return ordinal;
+    }
+
+    public void setOrdinal(int ordinal) {
+        this.ordinal = ordinal;
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigExecutableMember.java b/tools/signature-tools/src/signature/model/impl/SigExecutableMember.java
new file mode 100644
index 0000000..3203d59
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigExecutableMember.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import signature.model.IClassDefinition;
+import signature.model.IExecutableMember;
+import signature.model.IParameter;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+import signature.model.Modifier;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Set;
+
+@SuppressWarnings("serial")
+public abstract class SigExecutableMember extends SigAnnotatableElement
+        implements IExecutableMember, Serializable {
+
+    private String name;
+    private List<IParameter> parameters = Uninitialized.unset();
+    private Set<ITypeReference> exceptions = Uninitialized.unset();
+    private Set<Modifier> modifiers = Uninitialized.unset();
+    private List<ITypeVariableDefinition> typeParameters = Uninitialized
+            .unset();
+    private IClassDefinition declaringClass = Uninitialized.unset();
+
+    public SigExecutableMember(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public List<IParameter> getParameters() {
+        return parameters;
+    }
+
+    public void setParameters(List<IParameter> parameters) {
+        this.parameters = parameters;
+    }
+
+    public Set<ITypeReference> getExceptions() {
+        return exceptions;
+    }
+
+    public void setExceptions(Set<ITypeReference> exceptions) {
+        this.exceptions = exceptions;
+    }
+
+    public Set<Modifier> getModifiers() {
+        return modifiers;
+    }
+
+    public void setModifiers(Set<Modifier> modifiers) {
+        this.modifiers = modifiers;
+    }
+
+    public List<ITypeVariableDefinition> getTypeParameters() {
+        return typeParameters;
+    }
+
+    public void setTypeParameters(
+            List<ITypeVariableDefinition> typeParameters) {
+        this.typeParameters = typeParameters;
+    }
+
+    public IClassDefinition getDeclaringClass() {
+        return declaringClass;
+    }
+
+    public void setDeclaringClass(IClassDefinition declaringClass) {
+        this.declaringClass = declaringClass;
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigField.java b/tools/signature-tools/src/signature/model/impl/SigField.java
new file mode 100644
index 0000000..e305566
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigField.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import signature.model.IField;
+import signature.model.ITypeReference;
+import signature.model.Modifier;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Set;
+
+@SuppressWarnings("serial")
+public class SigField extends SigAnnotatableElement implements IField,
+        Serializable {
+
+    private String name;
+    private ITypeReference type = Uninitialized.unset();
+    private Set<Modifier> modifiers = Uninitialized.unset();
+
+    public SigField(String name) {
+        this.name = name;
+        modifiers = Collections.emptySet();
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Set<Modifier> getModifiers() {
+        return modifiers;
+    }
+
+    public void setModifiers(Set<Modifier> modifiers) {
+        this.modifiers = modifiers;
+    }
+
+    public ITypeReference getType() {
+        return type;
+    }
+
+    public void setType(ITypeReference type) {
+        this.type = type;
+    }
+
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        if (getAnnotations() != null && !getAnnotations().isEmpty()) {
+            builder.append(super.toString());
+            builder.append("\n");
+        }
+        builder.append(Modifier.toString(getModifiers()));
+        builder.append(getType().toString());
+        builder.append(" ");
+        builder.append(getName());
+        return builder.toString();
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigMethod.java b/tools/signature-tools/src/signature/model/impl/SigMethod.java
new file mode 100644
index 0000000..489397f
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigMethod.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import java.io.Serializable;
+
+import signature.model.IMethod;
+import signature.model.ITypeReference;
+import signature.model.Modifier;
+import signature.model.util.ModelUtil;
+
+@SuppressWarnings("serial")
+public class SigMethod extends SigExecutableMember implements IMethod,
+        Serializable {
+
+    private ITypeReference returnType = Uninitialized.unset();
+
+    public SigMethod(String name) {
+        super(name);
+    }
+
+
+    public ITypeReference getReturnType() {
+        return returnType;
+    }
+
+    public void setReturnType(ITypeReference returnType) {
+        this.returnType = returnType;
+    }
+
+    @Override
+    public String toString() {
+        return SigMethod.toString(this);
+    }
+
+    public static String toString(IMethod method) {
+        StringBuilder builder = new StringBuilder();
+        builder.append(Modifier.toString(method.getModifiers()));
+        builder.append(method.getReturnType());
+        builder.append(" ");
+        if (method.getTypeParameters() != null
+                && !method.getTypeParameters().isEmpty()) {
+            builder.append("<");
+            builder
+                    .append(ModelUtil
+                            .separate(method.getTypeParameters(), ", "));
+            builder.append("> ");
+        }
+        builder.append(method.getName());
+        builder.append("(");
+        builder.append(method.getParameters().isEmpty() ? "" : ModelUtil
+                .separate(method.getParameters(), ", "));
+        builder.append(")");
+        if (method.getExceptions() != null
+                && !method.getExceptions().isEmpty()) {
+            builder.append(" throws ");
+            builder.append(ModelUtil.separate(method.getExceptions(), " "));
+        }
+        return builder.toString();
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigPackage.java b/tools/signature-tools/src/signature/model/impl/SigPackage.java
new file mode 100644
index 0000000..686917c
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigPackage.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import signature.model.IClassDefinition;
+import signature.model.IPackage;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+@SuppressWarnings("serial")
+public class SigPackage extends SigAnnotatableElement implements IPackage,
+        Serializable {
+
+    private String name;
+    private Set<IClassDefinition> classes = Uninitialized.unset();
+
+    public SigPackage(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public List<String> getPackageFragments() {
+        return Arrays.asList(name.split("\\."));
+    }
+
+    public Set<IClassDefinition> getClasses() {
+        return classes;
+    }
+
+    public void setClasses(Set<IClassDefinition> classes) {
+        this.classes = classes;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("package: ");
+        builder.append(getName());
+        return builder.toString();
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigParameter.java b/tools/signature-tools/src/signature/model/impl/SigParameter.java
new file mode 100644
index 0000000..d9d3369
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigParameter.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import signature.model.IParameter;
+import signature.model.ITypeReference;
+
+import java.io.Serializable;
+
+@SuppressWarnings("serial")
+public class SigParameter extends SigAnnotatableElement implements IParameter,
+        Serializable {
+
+    private ITypeReference type;
+
+    public SigParameter(ITypeReference type) {
+        this.type = type;
+    }
+
+    public ITypeReference getType() {
+        return type;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append(super.toString());
+        builder.append(" ");
+        builder.append(getType().toString());
+        return builder.toString();
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigParameterizedType.java b/tools/signature-tools/src/signature/model/impl/SigParameterizedType.java
new file mode 100644
index 0000000..d726135
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigParameterizedType.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import signature.model.IClassReference;
+import signature.model.IParameterizedType;
+import signature.model.ITypeReference;
+import signature.model.util.ModelUtil;
+
+import java.io.Serializable;
+import java.util.List;
+
+@SuppressWarnings("serial")
+public class SigParameterizedType implements IParameterizedType, Serializable {
+
+    private ITypeReference ownerType;
+    private IClassReference rawType;
+    private List<ITypeReference> typeArguments;
+
+    public SigParameterizedType(ITypeReference ownerType,
+            IClassReference rawType, List<ITypeReference> typeArguments) {
+        this.ownerType = ownerType;
+        this.rawType = rawType;
+        this.typeArguments = typeArguments;
+    }
+
+    public ITypeReference getOwnerType() {
+        ITypeReference returnValue = ownerType;
+        if (returnValue == null) {
+            if (rawType.getClassDefinition().getDeclaringClass() != null) {
+                returnValue = new SigClassReference(rawType
+                        .getClassDefinition().getDeclaringClass());
+            }
+        }
+        return returnValue;
+    }
+
+    public IClassReference getRawType() {
+        return rawType;
+    }
+
+    public List<ITypeReference> getTypeArguments() {
+        return typeArguments;
+    }
+
+    @Override
+    public int hashCode() {
+        return hashCode(this);
+    }
+
+    public static int hashCode(IParameterizedType type) {
+        final int prime = 31;
+        int result = 1;
+        result = prime * type.getRawType().hashCode();
+        result = prime * result + type.getTypeArguments().hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return equals(this, obj);
+    }
+
+    public static boolean equals(IParameterizedType thiz, Object that) {
+        if (!(that instanceof IParameterizedType)) {
+            return false;
+        }
+        IParameterizedType other = (IParameterizedType) that;
+        if (thiz.getOwnerType() == null) {
+            if (other.getOwnerType() != null) {
+                return false;
+            }
+        } else if (Uninitialized.isInitialized(thiz.getOwnerType())) {
+            if (!Uninitialized.isInitialized(other.getOwnerType())) {
+                return false;
+            }
+        } else if (!thiz.getOwnerType().equals(other.getOwnerType())) {
+            return false;
+        }
+        if (!thiz.getRawType().equals(other.getRawType())) {
+            return false;
+        }
+        if (!thiz.getTypeArguments().equals(other.getTypeArguments())) {
+            return false;
+        }
+        return true;
+    }
+
+
+    @Override
+    public String toString() {
+        return SigParameterizedType.toString(this);
+    }
+
+    public static String toString(IParameterizedType type) {
+        StringBuilder builder = new StringBuilder();
+        if (type.getOwnerType() != null) {
+            builder.append(type.getOwnerType().toString());
+            builder.append("::");
+        }
+        builder.append(type.getRawType());
+        builder.append("<");
+        builder.append(ModelUtil.separate(type.getTypeArguments(), ", "));
+        builder.append(">");
+        return builder.toString();
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigPrimitiveType.java b/tools/signature-tools/src/signature/model/impl/SigPrimitiveType.java
new file mode 100644
index 0000000..2786169
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigPrimitiveType.java
@@ -0,0 +1,49 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * 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 signature.model.impl;

+

+import signature.model.IPrimitiveType;

+

+public enum SigPrimitiveType implements IPrimitiveType {

+    VOID_TYPE("void"), BOOLEAN_TYPE("boolean"), BYTE_TYPE("byte"), CHAR_TYPE(

+            "char"), SHORT_TYPE("short"), INT_TYPE("int"), LONG_TYPE("long"),

+            FLOAT_TYPE("float"), DOUBLE_TYPE("double");

+

+    private String name;

+

+    private SigPrimitiveType(String name) {

+        this.name = name;

+    }

+

+    public static SigPrimitiveType valueOfTypeName(String name) {

+        for (SigPrimitiveType primitive : values()) {

+            if (primitive.name.equals(name)) {

+                return primitive;

+            }

+        }

+        throw new IllegalArgumentException(name + " is not a primitive type");

+    }

+

+    public String getName() {

+        return name;

+    }

+

+    @Override

+    public String toString() {

+        return name;

+    }

+}

diff --git a/tools/signature-tools/src/signature/model/impl/SigTypeVariableDefinition.java b/tools/signature-tools/src/signature/model/impl/SigTypeVariableDefinition.java
new file mode 100644
index 0000000..e0f918e
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigTypeVariableDefinition.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import signature.model.IGenericDeclaration;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+import signature.model.util.ModelUtil;
+
+import java.io.Serializable;
+import java.util.List;
+
+@SuppressWarnings("serial")
+public class SigTypeVariableDefinition implements ITypeVariableDefinition,
+        Serializable {
+
+    private String name;
+    private IGenericDeclaration genericDeclaration;
+    private List<ITypeReference> upperBounds = Uninitialized.unset();
+
+    public SigTypeVariableDefinition(String name,
+            IGenericDeclaration genericDeclaration) {
+        this.name = name;
+        this.genericDeclaration = genericDeclaration;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public IGenericDeclaration getGenericDeclaration() {
+        return genericDeclaration;
+    }
+
+    public List<ITypeReference> getUpperBounds() {
+        return upperBounds;
+    }
+
+    public void setUpperBounds(List<ITypeReference> upperBounds) {
+        this.upperBounds = upperBounds;
+    }
+
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append(name);
+        if (getUpperBounds().size() != 1) {
+            builder.append(ModelUtil.separate(getUpperBounds(), ", "));
+        } else {
+            if (!ModelUtil.isJavaLangObject(getUpperBounds().get(0))) {
+                builder.append(getUpperBounds().get(0));
+            }
+        }
+        return builder.toString();
+    }
+
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigTypeVariableReference.java b/tools/signature-tools/src/signature/model/impl/SigTypeVariableReference.java
new file mode 100644
index 0000000..6bd2593
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigTypeVariableReference.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import java.io.Serializable;
+
+import signature.model.ITypeVariableDefinition;
+import signature.model.ITypeVariableReference;
+
+@SuppressWarnings("serial")
+public class SigTypeVariableReference implements ITypeVariableReference,
+        Serializable {
+
+    private ITypeVariableDefinition definition;
+
+    public SigTypeVariableReference(ITypeVariableDefinition definition) {
+        this.definition = definition;
+    }
+
+    public ITypeVariableDefinition getTypeVariableDefinition() {
+        return definition;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (getClass() == obj.getClass()) {
+            return getTypeVariableDefinition().equals(
+                    ((ITypeVariableReference) obj).getTypeVariableDefinition());
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return getTypeVariableDefinition().hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return getTypeVariableDefinition().getName();
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/SigWildcardType.java b/tools/signature-tools/src/signature/model/impl/SigWildcardType.java
new file mode 100644
index 0000000..c24ac23
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/SigWildcardType.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import signature.model.ITypeReference;
+import signature.model.IWildcardType;
+
+import java.io.Serializable;
+import java.util.List;
+
+@SuppressWarnings("serial")
+public class SigWildcardType implements IWildcardType, Serializable {
+
+    private ITypeReference lowerBound;
+    private List<ITypeReference> upperBounds;
+
+    public SigWildcardType(ITypeReference lowerBound,
+            List<ITypeReference> upperBounds) {
+        this.lowerBound = lowerBound;
+        this.upperBounds = upperBounds;
+    }
+
+    public ITypeReference getLowerBound() {
+        return lowerBound;
+    }
+
+    public List<ITypeReference> getUpperBounds() {
+        return upperBounds;
+    }
+
+    @Override
+    public int hashCode() {
+        return SigWildcardType.hashCode(this);
+    }
+
+    public static int hashCode(IWildcardType type) {
+        final int prime = 31;
+        int result = 1;
+        result = prime
+                + ((type.getLowerBound() == null) ? 0 : type.getLowerBound()
+                        .hashCode());
+        result = prime * result + type.getUpperBounds().hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return SigWildcardType.equals(this, obj);
+    }
+
+    public static boolean equals(IWildcardType thiz, Object obj) {
+        if (thiz == obj) return true;
+        if (obj == null) return false;
+        if (!(obj instanceof IWildcardType)) return false;
+        IWildcardType that = (IWildcardType) obj;
+        if (thiz.getLowerBound() == null) {
+            if (that.getLowerBound() != null) return false;
+        } else if (!thiz.getLowerBound().equals(that.getLowerBound()))
+            return false;
+        if (!thiz.getUpperBounds().equals(that.getUpperBounds())) return false;
+        return true;
+    }
+
+
+    @Override
+    public String toString() {
+        return SigWildcardType.toString(this);
+    }
+
+    public static String toString(IWildcardType thiz) {
+        StringBuilder builder = new StringBuilder();
+        builder.append("?");
+        if (thiz.getLowerBound() != null) {
+            builder.append(" ");
+            builder.append(" super ");
+            builder.append(thiz.getLowerBound());
+        }
+        if (!thiz.getUpperBounds().isEmpty()) {
+            builder.append(" extends ");
+            builder.append(thiz.getUpperBounds());
+        }
+        return builder.toString();
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/impl/Uninitialized.java b/tools/signature-tools/src/signature/model/impl/Uninitialized.java
new file mode 100644
index 0000000..cc88479
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/impl/Uninitialized.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.impl;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.List;
+import java.util.Set;
+
+import signature.model.IAnnotationField;
+import signature.model.IClassDefinition;
+import signature.model.IClassReference;
+import signature.model.IPackage;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+import signature.model.ITypeVariableReference;
+import signature.model.Kind;
+
+/**
+ *
+ */
+public class Uninitialized {
+
+    private static final Object UNINITIALIZED;
+
+    static {
+        UNINITIALIZED = Proxy.newProxyInstance(Uninitialized.class
+                .getClassLoader(), new Class[] {
+                ITypeReference.class, IPackage.class, IClassDefinition.class,
+                IClassReference.class, ITypeVariableReference.class,
+                ITypeVariableDefinition.class, IAnnotationField.class,
+                Set.class, List.class}, new InvocationHandler() {
+            public Object invoke(Object proxy, Method method, Object[] args)
+                    throws Throwable {
+                if (method.getName().equals("toString")) {
+                    return "Uninitialized";
+                }
+
+                throw new UnsupportedOperationException();
+            }
+        });
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T unset() {
+        return (T) UNINITIALIZED;
+    }
+
+    public static boolean isInitialized(Object o) {
+        return o != UNINITIALIZED && o != Kind.UNINITIALIZED;
+    }
+}
diff --git a/tools/signature-tools/src/signature/model/util/ITypeFactory.java b/tools/signature-tools/src/signature/model/util/ITypeFactory.java
new file mode 100644
index 0000000..af3e3a9
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/util/ITypeFactory.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.util;
+
+import signature.model.IClassReference;
+import signature.model.IGenericDeclaration;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableReference;
+import signature.model.impl.SigArrayType;
+import signature.model.impl.SigClassDefinition;
+import signature.model.impl.SigParameterizedType;
+import signature.model.impl.SigTypeVariableDefinition;
+import signature.model.impl.SigWildcardType;
+
+import java.util.List;
+
+public interface ITypeFactory {
+
+    public static final String JAVA_LANG_OBJECT = "java.lang.Object";
+
+    /**
+     * Returns the existing type or creates a new one.<br>
+     * Format: java.lang.Object
+     */
+    public SigClassDefinition getClass(String packageName, String className);
+
+    public IClassReference getClassReference(String packageName,
+            String className);
+
+    /**
+     * Returns the existing array type or creates a new one.
+     * 
+     * @param componentType
+     *            the component type of the array
+     * @return the array type
+     */
+    public SigArrayType getArrayType(ITypeReference componentType);
+
+    /**
+     * Returns the existing parameterized type or creates a new one.
+     * 
+     * @param ownerType
+     *            the owner of the parameterized type
+     * @param rawType
+     *            the type which is parameterized
+     * @param typeArguments
+     *            the type arguments
+     * @return the parameterized type
+     */
+    public SigParameterizedType getParameterizedType(ITypeReference ownerType,
+            IClassReference rawType, List<ITypeReference> typeArguments);
+
+
+    public boolean containsTypeVariableDefinition(String name,
+            IGenericDeclaration genericDeclaration);
+
+    /**
+     * Returns the existing type variable or creates a new one.
+     * 
+     * @param genericDeclaration
+     *            the declaration site of the variable
+     * @param name
+     *            the name of the type variable
+     * @return the type variable
+     */
+    public SigTypeVariableDefinition getTypeVariable(String name,
+            IGenericDeclaration genericDeclaration);
+
+    public ITypeVariableReference getTypeVariableReference(String name,
+            IGenericDeclaration genericDeclaration);
+
+    /**
+     * Returns the existing wildcard type or creates a new one. Wildcard types
+     * are equal if they have the same lower bound and have the same upper
+     * bounds. The order of the upper bounds is irrelevant except for the first
+     * element. <br>
+     * Note: This does not mean that two values with equal wildcard type can be
+     * assigned to each other!
+     * 
+     * @param lowerBound
+     *            the lower bound
+     * @param upperBounds
+     *            the upper bounds
+     * @return the wildcard type
+     */
+    public SigWildcardType getWildcardType(ITypeReference lowerBound,
+            List<ITypeReference> upperBounds);
+
+}
diff --git a/tools/signature-tools/src/signature/model/util/ModelUtil.java b/tools/signature-tools/src/signature/model/util/ModelUtil.java
new file mode 100644
index 0000000..f66fd2c
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/util/ModelUtil.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.util;
+
+import signature.model.IAnnotatableElement;
+import signature.model.IAnnotation;
+import signature.model.IAnnotationElement;
+import signature.model.IAnnotationField;
+import signature.model.IApi;
+import signature.model.IClassDefinition;
+import signature.model.IField;
+import signature.model.IPackage;
+import signature.model.ITypeReference;
+
+import java.util.Collection;
+
+public class ModelUtil {
+    private ModelUtil() {
+    }
+
+    /**
+     * Returns the IClass for the given className.<br>
+     * Format: a.b.C
+     * 
+     * @param qualifiedClassName
+     *            the fully qualified class name
+     * @return the IClass instance or null;
+     */
+    public static IClassDefinition getClass(IPackage aPackage,
+            String qualifiedClassName) {
+        for (IClassDefinition clazz : aPackage.getClasses()) {
+            if (qualifiedClassName.equals(clazz.getName())) {
+                return clazz;
+            }
+        }
+        return null;
+    }
+
+    public static IAnnotation getAnnotation(IAnnotatableElement element,
+            String qualifiedTypeName) {
+        for (IAnnotation annotation : element.getAnnotations()) {
+            if (qualifiedTypeName.equals(annotation.getType()
+                    .getClassDefinition().getQualifiedName())) {
+                return annotation;
+            }
+        }
+        return null;
+    }
+
+    public static IAnnotationElement getAnnotationElement(
+            IAnnotation annotation, String elementName) {
+        for (IAnnotationElement element : annotation.getElements()) {
+            if (elementName.equals(element.getDeclaringField().getName())) {
+                return element;
+            }
+        }
+        return null;
+    }
+
+    public static IField getField(IClassDefinition clazz, String fieldName) {
+        for (IField field : clazz.getFields()) {
+            if (fieldName.equals(field.getName())) {
+                return field;
+            }
+        }
+        return null;
+    }
+
+    public static IAnnotationField getAnnotationField(
+            IClassDefinition annotation, String fieldName) {
+        for (IAnnotationField field : annotation.getAnnotationFields()) {
+            if (fieldName.equals(field.getName())) {
+                return field;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the IPackage for the given className.<br>
+     * Format: a.b
+     * 
+     * @param api
+     *            the api
+     * @param packageName
+     *            the name of the package
+     * @return the IClass instance or null;
+     */
+    public static IPackage getPackage(IApi api, String packageName) {
+        for (IPackage aPackage : api.getPackages()) {
+            if (packageName.equals(aPackage.getName())) {
+                return aPackage;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * "a.b.c.A;" -> "a.b.c" "A" -> "" empty string
+     * 
+     * @param classIdentifier
+     * @return the package name
+     */
+    public static String getPackageName(String classIdentifier) {
+        int lastIndexOfSlash = classIdentifier.lastIndexOf('.');
+        String packageName = null;
+        if (lastIndexOfSlash == -1) {
+            packageName = "";
+        } else {
+            packageName = classIdentifier.substring(0, lastIndexOfSlash);
+        }
+        return packageName;
+    }
+
+    /**
+     * "a.b.c.A;" -> "A" "A" -> "A"
+     * 
+     * @param classIdentifier
+     *            fully qualified class name
+     * @return the class name
+     */
+    public static String getClassName(String classIdentifier) {
+        int lastIndexOfDot = classIdentifier.lastIndexOf('.');
+        String className = null;
+        if (lastIndexOfDot == -1) {
+            className = classIdentifier;
+        } else {
+            className = classIdentifier.substring(lastIndexOfDot + 1);
+        }
+        return className;
+    }
+
+
+    public static String separate(Collection<? extends Object> elements,
+            String separator) {
+        StringBuilder s = new StringBuilder();
+        boolean first = true;
+        for (Object object : elements) {
+            if (!first) {
+                s.append(separator);
+            }
+            s.append(object.toString());
+            first = false;
+        }
+        return s.toString();
+    }
+
+    public static boolean isJavaLangObject(ITypeReference type) {
+        if (type instanceof IClassDefinition) {
+            IClassDefinition clazz = (IClassDefinition) type;
+            if ("java.lang".equals(clazz.getPackageName())) {
+                return "Object".equals(clazz.getName());
+            }
+        }
+        return false;
+    }
+
+}
diff --git a/tools/signature-tools/src/signature/model/util/TypePool.java b/tools/signature-tools/src/signature/model/util/TypePool.java
new file mode 100644
index 0000000..dc48113
--- /dev/null
+++ b/tools/signature-tools/src/signature/model/util/TypePool.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.model.util;
+
+import static signature.model.impl.Uninitialized.isInitialized;
+import signature.model.IClassReference;
+import signature.model.IGenericDeclaration;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableReference;
+import signature.model.impl.SigArrayType;
+import signature.model.impl.SigClassDefinition;
+import signature.model.impl.SigClassReference;
+import signature.model.impl.SigParameterizedType;
+import signature.model.impl.SigTypeVariableDefinition;
+import signature.model.impl.SigTypeVariableReference;
+import signature.model.impl.SigWildcardType;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Pool and factory for all {@link ITypeReference} instances.<br>
+ * Note: This class is not thread save
+ */
+public class TypePool implements ITypeFactory {
+
+    /**
+     * Pool for all SigClass objects. Key format: "java.lang.Object", "a.b.C$D
+     */
+    private Map<String, SigClassDefinition> classPool;
+    /** Pool for all SigTypeVariable objects */
+    private Map<TypeVariableKey, SigTypeVariableDefinition> typeVariablePool;
+
+    public TypePool() {
+        classPool = new HashMap<String, SigClassDefinition>();
+        typeVariablePool =
+                new HashMap<TypeVariableKey, SigTypeVariableDefinition>();
+    }
+
+    public SigClassDefinition getClass(String packageName, String className) {
+        String key = packageName + "<>" + className;
+        SigClassDefinition clazz = classPool.get(key);
+        if (clazz == null) {
+            clazz = new SigClassDefinition(packageName, className);
+            classPool.put(key, clazz);
+        }
+        return clazz;
+    }
+
+    public IClassReference getClassReference(String packageName,
+            String className) {
+        return new SigClassReference(getClass(packageName, className));
+    }
+
+    public SigArrayType getArrayType(ITypeReference componentType) {
+        assert componentType != null;
+        return new SigArrayType(componentType);
+    }
+
+    public SigParameterizedType getParameterizedType(ITypeReference ownerType,
+            IClassReference rawType, List<ITypeReference> typeArguments) {
+        assert rawType != null;
+        assert typeArguments != null;
+        return new SigParameterizedType(ownerType, rawType, typeArguments);
+    }
+
+    private static class TypeVariableKey {
+        private String name;
+        private IGenericDeclaration genericDeclaration;
+
+        public TypeVariableKey(String name,
+                IGenericDeclaration genericDeclaration) {
+            this.genericDeclaration = genericDeclaration;
+            this.name = name;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + genericDeclaration.hashCode();
+            result = prime * result + name.hashCode();
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            TypeVariableKey other = (TypeVariableKey) obj;
+            if (genericDeclaration != other.genericDeclaration) {
+                return false;
+            }
+            if (!name.equals(other.name)) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    public boolean containsTypeVariableDefinition(String name,
+            IGenericDeclaration genericDeclaration) {
+        TypeVariableKey key = new TypeVariableKey(name, genericDeclaration);
+        return typeVariablePool.get(key) != null;
+    }
+
+    public SigTypeVariableDefinition getTypeVariable(String name,
+            IGenericDeclaration genericDeclaration) {
+        assert name != null;
+        assert genericDeclaration != null;
+
+        TypeVariableKey key = new TypeVariableKey(name, genericDeclaration);
+        SigTypeVariableDefinition sigTypeVariable = typeVariablePool.get(key);
+        if (sigTypeVariable == null) {
+            sigTypeVariable = new SigTypeVariableDefinition(name,
+                    genericDeclaration);
+            typeVariablePool.put(key, sigTypeVariable);
+        }
+        return sigTypeVariable;
+    }
+
+    public ITypeVariableReference getTypeVariableReference(String name,
+            IGenericDeclaration genericDeclaration) {
+        return new SigTypeVariableReference(getTypeVariable(name,
+                genericDeclaration));
+    }
+
+    public SigWildcardType getWildcardType(ITypeReference lowerBound,
+            List<ITypeReference> upperBounds) {
+        assert upperBounds != null;
+
+        SigWildcardType sigWildcardType = new SigWildcardType(lowerBound,
+                upperBounds);
+        return sigWildcardType;
+    }
+
+    public void replaceAllUninitialiezWithNull() {
+        for (SigClassDefinition clazz : classPool.values()) {
+            replaceUninitializedWithNull(clazz);
+        }
+    }
+
+    private static void replaceUninitializedWithNull(
+            SigClassDefinition clazz) {
+        if (clazz == null) {
+            return;
+        }
+        if (!isInitialized(clazz.getAnnotationFields())) {
+            clazz.setAnnotationFields(null);
+        }
+        if (!isInitialized(clazz.getAnnotations())) {
+            clazz.setAnnotations(null);
+        }
+        if (!isInitialized(clazz.getAnnotations())) {
+            clazz.setAnnotations(null);
+        }
+        if (!isInitialized(clazz.getConstructors())) {
+            clazz.setConstructors(null);
+        }
+        if (!isInitialized(clazz.getDeclaringClass())) {
+            clazz.setDeclaringClass(null);
+        }
+
+        if (!isInitialized(clazz.getEnumConstants())) {
+            clazz.setEnumConstants(null);
+        }
+        if (!isInitialized(clazz.getFields())) {
+            clazz.setFields(null);
+        }
+        if (!isInitialized(clazz.getInnerClasses())) {
+            clazz.setInnerClasses(null);
+        }
+        if (!isInitialized(clazz.getInterfaces())) {
+            clazz.setInterfaces(null);
+        }
+        if (!isInitialized(clazz.getKind())) {
+            clazz.setKind(null);
+        }
+        if (!isInitialized(clazz.getMethods())) {
+            clazz.setMethods(null);
+        }
+        if (!isInitialized(clazz.getModifiers())) {
+            clazz.setModifiers(null);
+        }
+        if (!isInitialized(clazz.getSuperClass())) {
+            clazz.setSuperClass(null);
+        }
+        if (!isInitialized(clazz.getTypeParameters())) {
+            clazz.setTypeParameters(null);
+        }
+    }
+}
diff --git a/tools/signature-tools/templates/ApiOverviewPage.st b/tools/signature-tools/templates/ApiOverviewPage.st
new file mode 100644
index 0000000..4faa193
--- /dev/null
+++ b/tools/signature-tools/templates/ApiOverviewPage.st
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN""http://www.w3.org/TR/REC-html40/frameset.dtd">
+<html>
+<head>
+$Common_meta()$
+<title>
+Android API Differences Report
+</title>
+<body>
+<div class="body">
+
+$Header()$
+
+
+<div class="content">
+<h2>Android API Differences Report</h2>
+<p>This document details the changes in the Android framework API. It shows 
+additions, modifications, and removals for packages, classes, methods, and 
+fields. Each reference to an API change includes a brief description of the 
+API and an explanation of the change and suggested workaround, where available.</p>
+
+<p>The differences described in this report are based a comparison of the APIs 
+whose versions are specified in the upper-right corner of this page. It compares a 
+newer "to" API to an older "from" version, noting any changes relative to the 
+older API. So, for example, indicated API removals are no longer present in the "to" 
+API.</p>
+<p>For more information about the Android framework API and SDK, 
+see the <a href="http://code.google.com/android/index.html" target="_top">Android product site</a>.</p>
+
+$if(no_delta)$
+<h3>Congratulation!</h3>
+No differences were detected between the two provided APIs.
+$endif$
+
+
+$if(removed_packages)$
+$Table(name="Removed Packages", rows=removed_packages:{$it.from:ModelElementRow()$})$
+<br/>
+$endif$
+
+
+$if(added_packages)$
+$Table(name="Added Packages", rows=added_packages:{$it.to:PackageAddedLink()$}:SimpleTableRow())$
+<br/>
+$endif$
+
+$if(changed_packages)$
+$Table(name="Changed Packages", rows=changed_packages:{$it.to:PackageChangedLink()$}:SimpleTableRow())$
+<br/>
+$endif$
+</div>
+
+
+</div>
+</body>
+</html>
+
+
+
+
+
diff --git a/tools/signature-tools/templates/ClassChangedLink.st b/tools/signature-tools/templates/ClassChangedLink.st
new file mode 100644
index 0000000..20e0ed9
--- /dev/null
+++ b/tools/signature-tools/templates/ClassChangedLink.st
@@ -0,0 +1 @@
+$Link(url={$it.packageName$.$it.name$.html}, name={<tt>$it.name$</tt>})$
diff --git a/tools/signature-tools/templates/ClassOverviewPage.st b/tools/signature-tools/templates/ClassOverviewPage.st
new file mode 100644
index 0000000..45b4c1c
--- /dev/null
+++ b/tools/signature-tools/templates/ClassOverviewPage.st
@@ -0,0 +1,131 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN""http://www.w3.org/TR/REC-html40/frameset.dtd">
+<html>
+<head>
+$Common_meta()$
+<title>
+$class_delta.to.packageName$.$class_delta.to.name$
+</title>
+</head>
+<body>
+
+<div class="body">
+
+$Header()$
+
+<div class="content">
+<h2>Class $class_delta.to.packageName$.$class_delta.to:ClassReferenceLink()$</h2>
+<br/>
+
+$if(has_class_signature_delta)$
+<table summary="Signature Difference" border="1" width="100%">
+  <tr>
+    <th colspan=3>Signature Difference</th>
+  </tr>
+  <tbody>
+    <tr class="default">
+      <td>$SigClassDefinition(element=class_delta.to)$</td>
+      <td>
+        $if(class_delta.annotationDeltas)$   $MultiSubDelta(desc="Annotations Changed:", deltas=class_delta.annotationDeltas)$      $endif$
+        $if(class_delta.modifierDeltas)$     $MultiSubDelta(desc="Modifiers Changed:", deltas=class_delta.modifierDeltas)$          $endif$
+        $if(class_delta.typeVariableDeltas)$ $MultiSubDelta(desc="Type Variables Changed:", deltas=class_delta.typeVariableDeltas)$ $endif$
+        $if(class_delta.superClassDelta)$    $SingleSubDelta(desc="Superclass Changed", delta=class_delta.superClassDelta)$               $endif$
+        $if(class_delta.interfaceDeltas)$    $MultiSubDelta(desc="Interfaces Changed:", deltas=class_delta.interfaceDeltas)$        $endif$
+      </td>
+    </tr>
+  </tbody>
+</table>
+<br/>
+$endif$
+
+$! Annotation Fields !$
+
+$if(removed_annotation_fields)$
+$Table(name="Removed Annotation Fields", rows=removed_annotation_fields:{$it.from:ModelElementRow()$})$
+<br/>
+$endif$
+
+$if(added_annotation_fields)$
+$Table(name="Added Annotation Fields", rows=added_annotation_fields:{$it.to:ModelElementRow()$})$
+<br/>
+$endif$
+
+$if(changed_annotation_fields)$
+$Table(name="Changed Annotation Fields", rows=changed_annotation_fields:DeltaTableRow())$
+<br/>
+$endif$
+
+
+$! --------Enum Constants-------- !$
+
+$if(removed_enum_constants)$
+$Table(name="Removed Enum Constants", rows=removed_enum_constants:{$it.from:ModelElementRow()$})$
+<br/>
+$endif$
+
+$if(added_enum_constants)$
+$Table(name="Added Enum Constants", rows=added_enum_constants:{$it.to:ModelElementRow()$})$
+<br/>
+$endif$
+
+$if(changed_enum_constants)$
+$Table(name="Changed Enum Constants", rows=changed_enum_constants:DeltaTableRow())$
+<br/>
+$endif$
+
+
+$! Fields !$
+
+$if(removed_fields)$
+$Table(name="Removed Fields", rows=removed_fields:{$it.from:ModelElementRow()$})$
+<br/>
+$endif$
+
+$if(added_fields)$
+$Table(name="Added Fields", rows=added_fields:{$it.to:ModelElementRow()$})$
+<br/>
+$endif$
+
+$if(changed_fields)$
+$Table(name="Changed Fields", rows=changed_fields:DeltaTableRow())$
+<br/>
+$endif$
+
+
+$! Constructors !$
+
+$if(removed_constructors)$
+$Table(name="Removed Constructors", rows=removed_constructors:{$it.from:ModelElementRow()$})$
+<br/>
+$endif$
+
+$if(added_constructors)$
+$Table(name="Added Constructors", rows=added_constructors:{$it.to:ModelElementRow()$})$
+<br/>
+$endif$
+
+$if(changed_constructors)$
+$Table(name="Changed Constructors", rows=changed_constructors:DeltaTableRow())$
+<br/>
+$endif$
+
+
+$! Methods !$
+
+$if(removed_methods)$
+$Table(name="Removed Methods", rows=removed_methods:{$it.from:ModelElementRow()$})$
+<br/>
+$endif$
+
+$if(added_methods)$
+$Table(name="Added Methods", rows=added_methods:{$it.to:ModelElementRow()$})$
+<br/>
+$endif$
+
+$if(changed_methods)$
+$Table(name="Changed Methods", rows=changed_methods:DeltaTableRow())$
+<br/>
+$endif$
+</div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/tools/signature-tools/templates/ClassReferenceLink.st b/tools/signature-tools/templates/ClassReferenceLink.st
new file mode 100644
index 0000000..c22e9b5
--- /dev/null
+++ b/tools/signature-tools/templates/ClassReferenceLink.st
@@ -0,0 +1 @@
+$Link(url={http://code.google.com/android/reference/$it.packageFragments; separator="/"$/$it.name$.html}, name={<tt>$it.name$</tt>})$
diff --git a/tools/signature-tools/templates/Common_meta.st b/tools/signature-tools/templates/Common_meta.st
new file mode 100644
index 0000000..8663781
--- /dev/null
+++ b/tools/signature-tools/templates/Common_meta.st
@@ -0,0 +1,12 @@
+<meta name="generator" content="Android signature tools v 1.0">
+<meta name="keywords" content="API difference, difference between two APIs, API diff">
+<link type="text/css" rel="stylesheet" href="../styles.css" title="Stylesheet"/>
+<link type="text/css" rel="stylesheet" href="styles.css" title="Stylesheet"/>
+
+<link rel="stylesheet" type="text/css" href="http://code.google.com/android/assets/codesite/codesite.css"/>
+<link rel="stylesheet" type="text/css" href="http://code.google.com/android/assets/codesite/semantic_headers.css"/>
+<link rel="stylesheet" type="text/css" href="http://code.google.com/android/assets/style.css"/> 
+
+
+
+
diff --git a/tools/signature-tools/templates/DeltaTableRow.st b/tools/signature-tools/templates/DeltaTableRow.st
new file mode 100644
index 0000000..4d0974c
--- /dev/null
+++ b/tools/signature-tools/templates/DeltaTableRow.st
@@ -0,0 +1,8 @@
+<tr class="deltaTableRow">
+  <td class="element">
+    $ElementType(element=it.to):{<tt>$it$</tt>}$
+  </td>
+  <td class="delta">
+    $DeltaTypeSwitch(delta=it)$
+  </td>
+</tr>
diff --git a/tools/signature-tools/templates/Header.st b/tools/signature-tools/templates/Header.st
new file mode 100644
index 0000000..9aa8e2f
--- /dev/null
+++ b/tools/signature-tools/templates/Header.st
@@ -0,0 +1,21 @@
+<div class="header">
+  <div class="logo">
+    <a href="http://code.google.com/android/documentation.html"><img style="border: 0;" src="http://code.google.com/android/images/android_icon_125.png"/></a>
+  </div>
+  <div class="specbox">
+    <table>
+      <tr>
+        <th colspan="2"> API Diff Specification </th>
+      </tr>
+      <tr>
+        <td>To Version:</td> <td>$to_desc$</td>
+      </tr>
+      <tr>
+        <td>From Version:</td> <td>$from_desc$</td>
+      </tr>
+      <tr>
+        <td>Generated</td> <td>$creation_time$</td>
+      </tr>
+    </table>
+  </div>
+</div>
\ No newline at end of file
diff --git a/tools/signature-tools/templates/Link.st b/tools/signature-tools/templates/Link.st
new file mode 100644
index 0000000..2421094
--- /dev/null
+++ b/tools/signature-tools/templates/Link.st
@@ -0,0 +1 @@
+<a class="$link_style; null="default"$" href="$url$">$name$</a>
\ No newline at end of file
diff --git a/tools/signature-tools/templates/ModelElementRow.st b/tools/signature-tools/templates/ModelElementRow.st
new file mode 100644
index 0000000..54b20c6
--- /dev/null
+++ b/tools/signature-tools/templates/ModelElementRow.st
@@ -0,0 +1,6 @@
+<tr class="deltaTableRow">
+  <td class="element">
+    $ElementType(element=it):{<tt>$it$</tt>}$
+  </td>
+</tr>
+
diff --git a/tools/signature-tools/templates/PackageAddedLink.st b/tools/signature-tools/templates/PackageAddedLink.st
new file mode 100644
index 0000000..eb352da
--- /dev/null
+++ b/tools/signature-tools/templates/PackageAddedLink.st
@@ -0,0 +1 @@
+$Link(url={http://code.google.com/android/reference/$it.packageFragments; separator="/"$/package-summary.html}, name={<tt>$it.name$</tt>})$
diff --git a/tools/signature-tools/templates/PackageChangedLink.st b/tools/signature-tools/templates/PackageChangedLink.st
new file mode 100644
index 0000000..5951f2a
--- /dev/null
+++ b/tools/signature-tools/templates/PackageChangedLink.st
@@ -0,0 +1 @@
+$Link(url={changes/pkg_$it.name$.html}, name={<tt>$it.name$</tt>})$
\ No newline at end of file
diff --git a/tools/signature-tools/templates/PackageOverviewPage.st b/tools/signature-tools/templates/PackageOverviewPage.st
new file mode 100644
index 0000000..ebeded0
--- /dev/null
+++ b/tools/signature-tools/templates/PackageOverviewPage.st
@@ -0,0 +1,39 @@
+<!doctype html public "-//w3c//dtd html 4.0 frameset//en""http://www.w3.org/tr/rec-html40/frameset.dtd">
+<html>
+<head>
+$Common_meta()$
+<title>
+Android API Differences Report
+</title>
+<body>
+
+<div class="body">
+
+$Header()$
+
+<div class="content">
+
+<h2>
+Package $Link(url={http://code.google.com/android/reference/$package_delta.to.packageFragments; separator="/"$/package-summary.html}, name=package_delta.to.name)$
+</h2>
+
+
+$if(removed_classes)$
+$Table(name="Removed Classes and Interfaces", rows=removed_classes:{$it.from:{<tt>$it.name$</tt>}$}:SimpleTableRow())$
+<br/>
+$endif$
+
+
+$if(added_classes)$
+$Table(name="Added Classes and Interfaces", rows=added_classes:{$it.to:ClassReferenceLink()$}:SimpleTableRow())$
+<br/>
+$endif$
+
+$if(changed_classes)$
+$Table(name="Changed Classes and Interfaces", rows=changed_classes:{$it.to:ClassChangedLink()$}:SimpleTableRow())$
+<br/>
+$endif$
+</div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/tools/signature-tools/templates/SimpleTableRow.st b/tools/signature-tools/templates/SimpleTableRow.st
new file mode 100644
index 0000000..3e7e7c2
--- /dev/null
+++ b/tools/signature-tools/templates/SimpleTableRow.st
@@ -0,0 +1,5 @@
+<tr class="default">
+  <td>
+    $it$
+  </td>
+</tr>
diff --git a/tools/signature-tools/templates/Styles.st b/tools/signature-tools/templates/Styles.st
new file mode 100644
index 0000000..4294eb3
--- /dev/null
+++ b/tools/signature-tools/templates/Styles.st
@@ -0,0 +1,44 @@
+/*
+ * Noser signature html output v$version$
+ */
+
+/* default link style*/
+a.default:link      {color: blue; text-decoration: none}
+a.default:hover     {color: blue; text-decoration: underline;}
+a.default:visited   {color: blue; text-decoration: none}
+
+/* discreet link style */
+a.discreet:link     {color: black; text-decoration: none}
+a.discreet:visited  {color: black; text-decoration: none}
+a.discreet:hover    {color: black; text-decoration: underline;}
+
+ul { 
+	list-style-type: none 
+}
+
+.body {
+	margin: 10px;
+}
+
+.header {
+    position:relative;
+	width: 100%;
+	
+}
+
+.logo {
+	left:0px;
+}
+.specbox {
+    position:absolute;
+	right:0px;
+	top:0px;
+}
+
+.content {
+	width: 100%;
+	position: relative;
+	top:75px;
+}
+
+
diff --git a/tools/signature-tools/templates/Table.st b/tools/signature-tools/templates/Table.st
new file mode 100644
index 0000000..2eecb8e
--- /dev/null
+++ b/tools/signature-tools/templates/Table.st
@@ -0,0 +1,9 @@
+<table summary="$name$" border="1" width="100%">
+<tr>
+  <th COLSPAN=2>$name$</th>
+</tr>
+<tbody>
+$rows$
+</tbody>
+</table>
+
diff --git a/tools/signature-tools/templates/delta/deltas.stg b/tools/signature-tools/templates/delta/deltas.stg
new file mode 100644
index 0000000..a27d641
--- /dev/null
+++ b/tools/signature-tools/templates/delta/deltas.stg
@@ -0,0 +1,149 @@
+group deltas;
+
+
+ADDED(delta)  ::= "Added $ElementType(element=delta.to)$"
+
+
+REMOVED(delta) ::= "Removed $ElementType(element=delta.from)$"
+
+
+CHANGED(delta) ::= "$DeltaType(delta)$"
+
+
+DeltaType(delta) ::= "$({$delta.class.simpleName$})(delta)$"
+
+
+DeltaTypeSwitch(delta) ::= "$delta:({$delta.type$})(delta)$"
+
+
+MultiSubDelta(desc, deltas) ::= <<
+$if(deltas)$
+$if(!deltas.empty)$
+$desc$
+<ul>
+$deltas:{<li>$DeltaTypeSwitch(delta=it)$</li>}$
+</ul>
+$endif$
+$endif$ 
+>>
+
+
+SigAnnotationDelta(delta) ::= <<
+$MultiSubDelta(desc="Annotation Elements changed:", deltas=delta.annotationElementDeltas)$
+>>
+
+
+
+SigAnnotationElementDelta(delta) ::= <<
+$SingleSubDelta(desc="Value changed:", delta=delta.valueDelta)$
+>>
+
+
+SigArrayTypeDelta(delta) ::= <<
+$SingleSubDelta(desc="Component Type of array changed:", delta=delta.componentTypeDelta)$
+>>
+
+
+SigClassReferenceDelta(delta) ::= "from $SigClass(element=delta.from)$ to $SigClass(element=delta.to)$"
+
+
+SigConstructorDelta(delta) ::= "$SigExecutableMemberDelta(delta=delta)$"
+
+SigMethodDelta(delta) ::= <<
+$SigExecutableMemberDelta(delta=delta)$
+$if(delta.returnTypeDelta)$
+$SingleSubDelta(desc="Return Type changed:", delta=delta.returnTypeDelta)$
+$endif$
+>>
+
+
+SigExecutableMemberDelta(delta) ::= <<
+$if(delta.annotationDeltas)$
+$MultiSubDelta(desc="Annotations changed:", deltas=delta.annotationDeltas)$
+$endif$
+
+$if(delta.modifierDeltas)$
+$MultiSubDelta(desc="Modifiers changed:", deltas=delta.modifierDeltas)$
+$endif$
+
+$if(delta.typeVariableDeltas)$
+$MultiSubDelta(desc="Type Variables changed:", deltas=delta.typeVariableDeltas)$
+$endif$
+
+$if(delta.exceptionDeltas)$
+$MultiSubDelta(desc="Exceptions changed:", deltas=delta.exceptionDeltas)$
+$endif$
+
+$if(delta.parameterDeltas)$
+$MultiSubDelta(desc="Parameters changed:", deltas=delta.parameterDeltas)$
+$endif$
+>>
+
+SigFieldDelta(delta) ::= <<
+$SingleSubDelta(desc="Type changed:", delta=delta.typeDelta)$
+$MultiSubDelta(desc="Modifiers changed:", deltas=delta.modifierDeltas)$
+$MultiSubDelta(desc="Annotations changed:", deltas=delta.annotationDeltas)$
+>>
+
+SigGenericDelclarationDelta(delta) ::= "GenericDelclarationDelta $delta$"
+
+SigModifierDelta(delta) ::= "SigModifierDelta.st: Please file a bug if you see this message"
+
+
+SigParameterDelta(delta) ::= <<
+$if(delta.annotationDeltas)$
+$MultiSubDelta(desc="Annotations changed:", deltas=delta.annotationDeltas)$
+$endif$
+
+$if(delta.typeDelta)$
+$SingleSubDelta(desc="Type changed:", delta=delta.typeDelta)$
+$endif$
+>>
+
+
+SigParameterizedTypeDelta(delta) ::= <<
+$SingleSubDelta(desc="Owner Type changed:", delta=delta.ownerTypeDelta)$
+$SingleSubDelta(desc="Raw Type changed:", delta=delta.rawTypeDelta)$
+$MultiSubDelta(desc="Type Arguments changed:", deltas=delta.argumentTypeDeltas)$
+>>
+
+
+SigPrimitiveTypeDelta(delta) ::= "from $delta.from$ to $delta.to$"
+
+SigTypeDelta(delta) ::= "from $ElementType(element=delta.from)$ to $ElementType(element=delta.to)$"
+
+SigTypeVariableReferenceDelta(delta) ::= <<
+SigTypeVariableReferenceDelta:
+$delta$
+>>
+
+SigTypeVariableDefinitionDelta(delta) ::= <<
+$SingleSubDelta(desc="Upper Bound changed:", delta=delta.upperBoundsDelta)$
+$SingleSubDelta(desc="Declaration changed:", delta=delta.genericDeclarationDelta)$
+>>
+
+SigUpperBoundsDelta(delta) ::= <<
+$SingleSubDelta(desc="First Upper Bound changed:", delta=delta.firstUpperBoundDelta)$
+$MultiSubDelta(desc="Upper Bounds changed:", deltas=delta.remainingUpperBoundDeltas)$
+>>
+
+SigWildcardTypeDelta(delta) ::= <<
+$SingleSubDelta(desc="Lower Bound changed:", delta=delta.lowerBoundDelta)$
+$SingleSubDelta(desc="Upper Bounds changed:", delta=delta.upperBoundDelta)$
+>>
+
+SigAnnotationFieldDelta(delta) ::= <<
+$SigFieldDelta(delta = delta)$
+$SingleSubDelta(desc="Default value changed:", delta=delta.defaultValueDelta)$
+>>
+
+SingleSubDelta(desc, delta) ::= <<
+$if(delta)$
+$desc$
+<ul>
+  <li>$DeltaTypeSwitch(delta=delta)$</li>
+</ul>
+$endif$
+>>
+
+
diff --git a/tools/signature-tools/templates/model/model.stg b/tools/signature-tools/templates/model/model.stg
new file mode 100644
index 0000000..425ad36
--- /dev/null
+++ b/tools/signature-tools/templates/model/model.stg
@@ -0,0 +1,135 @@
+group model;
+
+ElementType(element) ::= <<
+$({$element.class.simpleName$})(element = element)$
+>>
+
+Modifier(element) ::= <<
+$element$
+>>
+
+SigAnnotation(element) ::= <<
+@$ElementType(element = element.type)$
+$if(element.elements)$
+{$element.elements:{$SigAnnotationElement(element=it)$}$}
+$endif$
+>>
+
+SigAnnotationElement(element) ::= <<
+$element.declaringField.name$=$element.value$
+>>
+
+SigAnnotationField(element) ::= <<
+$SigField(element = element)$ $if(element.defaultValue)$ default=$element.defaultValue$$endif$
+>>
+
+SigArrayType(element) ::= <<
+$ElementType(element = element.componentType)$[]
+>>
+
+
+SigClassDefinition(element) ::= <<
+$Annotations(element = element)$
+$Modifiers(element = element)$$element.kind$ $element:ClassReferenceLink(link_style="discreet")$
+$TypeParameters(element = element)$
+$if(element.superClass)$ extends $ElementType(element=element.superClass)$$endif$
+$if(element.interfaces)$ implements $element.interfaces:{$ElementType(element=it)$}; separator=", "$$endif$
+>>
+
+ClassReferenceProjection(element) ::= <<
+$SigClassReference(element= element)$
+>>
+
+SigClassReference(element) ::= <<
+$ClassReferenceLink(it = element.classDefinition, link_style="discreet")$
+>>
+
+SigConstructor(element) ::= <<
+$Annotations(element= element, separator=" ")$
+$Modifiers(element= element)$
+$TypeParameters(element= element)$
+$SigExecutableMember(element= element)$
+>>
+
+//FIXME add SigEnumConstantReference to format correct in either case
+SigEnumConstant(element) ::= <<
+enum constant $ElementType(element=element.type)$.$element.name$
+>>
+
+SigExecutableMember(element) ::= <<
+$element.name$($element.parameters:{$SigParameter(element=it)$}; separator=", "$)
+$if(element.exceptions)$ throws $element.exceptions:{$ElementType(element=it)$}; separator=", "$$endif$
+>>
+
+SigField(element) ::= <<
+$Annotations(element = element, separator="<br/>")$
+$Modifiers(element = element)$$ElementType(element=element.type)$ $element.name$
+>>
+
+MethodProjection(element) ::= <<
+$SigMethod(element=element)$
+>>
+
+SigMethod(element) ::= <<
+$Annotations(element=element)$
+$Modifiers(element=element)$
+$TypeParameters(element=element)$
+$ElementType(element=element.returnType)$ $SigExecutableMember(element = element)$
+>>
+
+SigPackage(element) ::= <<
+$element.name$
+>>
+
+SigParameter(element) ::= <<
+$Annotations(element = element, separator=" ")$
+$ElementType(element=element.type)$
+>>
+
+ParameterizedTypeProjection(element) ::= <<
+$SigParameterizedType(element = element)$
+>>
+
+SigParameterizedType(element) ::= <<
+$if(element.ownerType)$$ElementType(element=element.ownerType)$$endif$
+$SigClassReference(element=element.rawType)$
+$if(element.typeArguments)$&lt;$element.typeArguments:{$ElementType(element=it)$}$&gt;$endif$
+>>
+
+SigPrimitiveType(element) ::= <<
+$element.name$
+>>
+
+SigTypeVariableDefinition(element) ::= <<
+$element.name$$if(!element.upperBounds.empty)$ extends $element.upperBounds:{$ElementType(element=it)$}; separator=", "$$endif$
+>>
+
+SigTypeVariableReference(element) ::= <<
+$element.typeVariableDefinition.name$
+>>
+
+SigWildcardType(element) ::= <<
+?
+$if(element.lowerBound)$ super $ElementType(element=element.lowerBound)$$endif$
+$if(!element.upperBounds.empty)$ extends $element.upperBounds:{$ElementType(element=it)$}; separator=", "$$endif$
+>>
+
+
+/* helper templates*/
+
+Modifiers(element) ::= <<
+$if(element.modifiers)$
+$element.modifiers; separator=" "$$\ $
+$endif$
+>>
+
+Annotations(element, separator) ::= <<
+$if(element.annotations)$
+$element.annotations:{$SigAnnotation(element=it)$}; separator=separator$
+$separator$
+$endif$
+>>
+
+TypeParameters(element) ::= <<
+$if(element.typeParameters)$ &lt;$element.typeParameters:{$SigTypeVariableDefinition(element=it)$}; separator=", "$&gt;$endif$
+>>
diff --git a/tools/signature-tools/test/signature/comparator/AllDexTests.java b/tools/signature-tools/test/signature/comparator/AllDexTests.java
new file mode 100644
index 0000000..b44dcb6
--- /dev/null
+++ b/tools/signature-tools/test/signature/comparator/AllDexTests.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.comparator;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+import signature.converter.dex.DexTestConverter;
+import signature.converter.util.ITestSourceConverter;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    AllDexTests.DexPackageCompareTest.class,
+    AllDexTests.DexClassCompareTest.class,
+    AllDexTests.DexMethodCompareTests.class,
+    AllDexTests.DexAnnotationCompareTest.class
+})
+public class AllDexTests {
+    private static ITestSourceConverter newConverter(){
+        return new DexTestConverter();
+    }
+    
+    public static class DexPackageCompareTest extends PackageCompareTest {
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+    
+    public static class DexClassCompareTest extends ClassCompareTest {
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+    
+    public static class DexMethodCompareTests extends MethodCompareTests {
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+    
+    public static class DexAnnotationCompareTest extends AnnotationCompareTest{
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+    
+    
+}
\ No newline at end of file
diff --git a/tools/signature-tools/test/signature/comparator/AllDocletTests.java b/tools/signature-tools/test/signature/comparator/AllDocletTests.java
new file mode 100644
index 0000000..327d931
--- /dev/null
+++ b/tools/signature-tools/test/signature/comparator/AllDocletTests.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.comparator;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+import signature.converter.doclet.DocletTestConverter;
+import signature.converter.util.ITestSourceConverter;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    AllDocletTests.DocletPackageCompareTest.class,
+    AllDocletTests.DocletClassCompareTest.class,
+    AllDocletTests.DocletMethodCompareTests.class
+})
+public class AllDocletTests {
+    private static ITestSourceConverter newConverter(){
+        return new DocletTestConverter();
+    }
+    
+    public static class DocletPackageCompareTest extends PackageCompareTest {
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+    
+    public static class DocletClassCompareTest extends ClassCompareTest {
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+    
+    public static class DocletMethodCompareTests extends MethodCompareTests {
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+}
\ No newline at end of file
diff --git a/tools/signature-tools/test/signature/comparator/AnnotationCompareTest.java b/tools/signature-tools/test/signature/comparator/AnnotationCompareTest.java
new file mode 100644
index 0000000..c72b637
--- /dev/null
+++ b/tools/signature-tools/test/signature/comparator/AnnotationCompareTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.comparator;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+
+import signature.comparator.util.AbstractComparatorTest;
+import signature.converter.util.CompilationUnit;
+import signature.model.IApi;
+
+import java.io.IOException;
+
+public abstract class AnnotationCompareTest extends AbstractComparatorTest {
+
+    @Test
+    public void testAnnotationValue() throws IOException{
+        CompilationUnit A0 = new CompilationUnit("a.A0", 
+                "package a; " +
+                "public @interface A0 {" +
+                "  A1 value() default @A1;" + 
+                "}");
+        CompilationUnit A1 = new CompilationUnit("a.A1", 
+                "package a; " +
+                "public @interface A1 {" +
+                "}");
+         CompilationUnit AnnotBDefault = new CompilationUnit("a.B", 
+                    "package a; " +
+                    "@A0 " +
+                    "public class B {}");
+         CompilationUnit AnnotB = new CompilationUnit("a.B", 
+                    "package a; " +
+                    "@A0 " +
+                    "public class B {}");
+          IApi fromApi = convert(A0, A1, AnnotBDefault);
+          IApi toApi = convert(A0, A1, AnnotB);
+          assertNull(compare(fromApi, toApi));
+    }
+    
+       @Test
+        public void testDefaultAnnotationValue() throws IOException{
+             CompilationUnit A0 = new CompilationUnit("a.A0", 
+                    "package a; " +
+                    "public @interface A0 {" +
+                    "  String value() default \"bla\";" +
+                    "}");
+             CompilationUnit A1 = new CompilationUnit("a.A0", 
+                    "package a; " +
+                    "public @interface A0 {" +
+                    "  String value();" + 
+                    "}");
+              IApi fromApi = convert(A0);
+              IApi toApi = convert(A1);
+              assertNotNull(compare(fromApi, toApi));
+        }
+}
diff --git a/tools/signature-tools/test/signature/comparator/ClassCompareTest.java b/tools/signature-tools/test/signature/comparator/ClassCompareTest.java
new file mode 100644
index 0000000..7171978
--- /dev/null
+++ b/tools/signature-tools/test/signature/comparator/ClassCompareTest.java
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.comparator;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+import org.junit.Test;
+
+import signature.comparator.util.AbstractComparatorTest;
+import signature.compare.model.IAnnotationDelta;
+import signature.compare.model.IApiDelta;
+import signature.compare.model.IClassDefinitionDelta;
+import signature.compare.model.DeltaType;
+import signature.compare.model.ITypeReferenceDelta;
+import signature.converter.util.CompilationUnit;
+import signature.model.IApi;
+
+import java.io.IOException;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.Set;
+
+public abstract class ClassCompareTest extends AbstractComparatorTest {
+
+    @Test
+    public void compareEqualClasses() throws IOException{
+         CompilationUnit A = new CompilationUnit("a.A", 
+                    "package a; " +
+                    "public class A {}");
+         CompilationUnit B = new CompilationUnit("a.B", 
+                    "package a; " +
+                    "public class B {}");
+          IApi fromApi = convert(A, B);
+          IApi toApi = convert(A, B);
+          assertNull(compare(fromApi, toApi));
+    }
+
+    @Test
+    public void compareMissingClass() throws IOException{
+         CompilationUnit A = new CompilationUnit("a.A", 
+                    "package a; " +
+                    "public class A {}");
+         CompilationUnit B = new CompilationUnit("a.B", 
+                    "package a; " +
+                    "public class B {}");
+          IApi fromApi = convert(A, B);
+          IApi toApi = convert(A);
+          
+          IApiDelta delta = compare(fromApi, toApi);
+          IClassDefinitionDelta classDelta = getSingleClassDelta(delta);
+          assertSame(DeltaType.REMOVED, classDelta.getType());
+    }
+    
+    @Test
+    public void compareAddedClass() throws IOException{
+         CompilationUnit A = new CompilationUnit("a.A", 
+                    "package a; " +
+                    "public class A {}");
+         CompilationUnit B = new CompilationUnit("a.B", 
+                    "package a; " +
+                    "public class B {}");
+          IApi fromApi = convert(A);
+          IApi toApi = convert(A, B);
+          
+          IApiDelta delta = compare(fromApi, toApi);
+          IClassDefinitionDelta classDelta = getSingleClassDelta(delta);
+          assertSame(DeltaType.ADDED, classDelta.getType());
+    }
+    
+    @Test
+    public void compareAnnotationsOnClass() throws IOException{
+         CompilationUnit A = new CompilationUnit("a.A", 
+                    "package a; " +
+                    "public class A {}");
+         CompilationUnit AnnotA = new CompilationUnit("a.A", 
+                    "package a; " +
+                    "@Deprecated " +
+                    "public class A {}");
+          IApi fromApi = convert(A);
+          IApi toApi = convert(AnnotA);
+          
+          IApiDelta delta = compare(fromApi, toApi);
+          IClassDefinitionDelta classDelta = getSingleClassDelta(delta);
+          
+          System.out.println(classDelta);
+          
+          Set<IAnnotationDelta> annotationDeltas = classDelta.getAnnotationDeltas();
+          assertEquals(1, annotationDeltas.size());
+          
+          IAnnotationDelta annotationDelta = annotationDeltas.iterator().next();
+          assertSame(DeltaType.ADDED, annotationDelta.getType());
+    }
+    
+    @Test
+    public void compareDefaultedAnnotationElementOnClass() throws IOException{
+        CompilationUnit annot = new CompilationUnit("a.A", 
+                "package a; " +
+                "public @interface A {" +
+                "  String name() default \"NAME\" ;" + 
+                "}");
+         CompilationUnit AnnotBDefault = new CompilationUnit("a.B", 
+                    "package a; " +
+                    "@A " +
+                    "public class B {}");
+         CompilationUnit AnnotB = new CompilationUnit("a.B", 
+                    "package a; " +
+                    "@A(name=\"NAME\") " +
+                    "public class B {}");
+          IApi fromApi = convert(annot, AnnotBDefault);
+          IApi toApi = convert(annot, AnnotB);
+          assertNull(compare(fromApi, toApi));
+    }
+    
+    @Test
+    public void compareSameInterfaces() throws IOException{
+         CompilationUnit A = new CompilationUnit("a.A", 
+                    "package a; " +
+                    "public class A implements Comparable<String>{ " +
+                    "  public int compareTo(String another){return 0;}" +
+                    "}");
+          IApi fromApi = convert(A);
+          IApi toApi = convert(A);
+          assertNull(compare(fromApi, toApi));
+    }
+    
+    @Test
+    public void compareMissingInterface() throws IOException{
+         CompilationUnit A0 = new CompilationUnit("a.A", 
+                 "package a; " +
+                 "public class A implements Cloneable{}");
+         CompilationUnit A1 = new CompilationUnit("a.A", 
+                 "package a; " +
+                 "public class A {}");
+          IApi fromApi = convert(A0);
+          IApi toApi = convert(A1);
+          IApiDelta apiDelta = compare(fromApi, toApi);
+          IClassDefinitionDelta classDelta =  getSingleClassDelta(apiDelta);
+          assertEquals(1, classDelta.getInterfaceDeltas().size());
+          ITypeReferenceDelta<?> interfaceDelta = classDelta.getInterfaceDeltas().iterator().next();
+          assertNotNull(interfaceDelta);
+    }
+    
+    @Test
+    public void compareMissingGenericInterface0() throws IOException{
+        CompilationUnit I = new CompilationUnit("a.I", 
+                "package a; " +
+                "public interface I<T>{}");
+        CompilationUnit B = new CompilationUnit("a.B", 
+                "package a; " +
+                "public class B implements I<String>{}");
+         CompilationUnit A0 = new CompilationUnit("a.A", 
+                "package a; " +
+                "public class A extends B implements I<String>{}");
+         CompilationUnit A1 = new CompilationUnit("a.A", 
+                 "package a; " +
+                 "public class A extends B {}");
+          IApi fromApi = convert(I, B, A0);
+          IApi toApi = convert(I, B, A1);
+          IApiDelta apiDelta = compare(fromApi, toApi);
+          assertNull(apiDelta);
+    }
+    
+    @Test
+    public void compareMissingGenericInterface1() throws IOException{
+        CompilationUnit I = new CompilationUnit("a.I", 
+                "package a; " +
+                "public interface I<T>{}");
+        CompilationUnit B = new CompilationUnit("a.B", 
+                "package a; " +
+                "public class B<T> implements I<T>{}");
+         CompilationUnit A0 = new CompilationUnit("a.A", 
+                "package a; " +
+                "public class A<T> extends B<T> implements I<T>{}");
+                 //generic declaration of 'T' in I<T> is A<T>
+         CompilationUnit A1 = new CompilationUnit("a.A", 
+                 "package a; " +
+                 "public class A<T> extends B<T> {}");
+                 //generic declaration of 'T' in I<T> is B<T>
+          IApi fromApi = convert(I, B, A0);
+          IApi toApi = convert(I, B, A1);
+          IApiDelta apiDelta = compare(fromApi, toApi);
+          assertNull(apiDelta);
+    }
+    
+    static interface I<T>{}
+    static class B<T> implements I<T>{}
+    static class A0<E extends Number> extends B<E> implements I<E>{}
+    static class A1<S extends Number> extends B<S>{}
+    
+    @Test
+    public void compareMissingGenericInterfaceReflection() {
+        ParameterizedType sC = (ParameterizedType)A0.class.getGenericSuperclass();
+        Type[] bounds = ((TypeVariable<?>)sC.getActualTypeArguments()[0]).getBounds();
+        Type[] a1Int = A1.class.getGenericInterfaces();
+        assertEquals(0,a1Int.length);
+    }
+    
+    @Test
+    public void compareInterfaceClosure() throws IOException{
+         CompilationUnit I0 = new CompilationUnit("a.I0", 
+                 "package a; " +
+                 "public interface I0{}");
+         CompilationUnit I1 = new CompilationUnit("a.I1", 
+                 "package a; " +
+                 "public interface I1 extends I0{}");
+         CompilationUnit C0 = new CompilationUnit("a.C0", 
+                 "package a; " +
+                 "public class C0 implements I1{}");
+         CompilationUnit C0_I1 = new CompilationUnit("a.C0", 
+                 "package a; " +
+                 "public class C0 implements I1, I0{}");
+          IApi fromApi = convert(I0, I1, C0);
+          IApi toApi = convert(I0, I1, C0_I1);
+          IApiDelta apiDelta = compare(fromApi, toApi);
+          assertNull(apiDelta);
+    }
+    
+    @Test
+    public void compareUpperBounds0() throws IOException{
+        CompilationUnit Number = new CompilationUnit("a.Number", 
+                    "package a; " +
+                    "public class Number implements java.io.Serializable{}");
+         CompilationUnit I0 = new CompilationUnit("a.I", 
+                    "package a; " +
+                    "public interface I<T extends Number & java.io.Serializable>{}");
+         CompilationUnit I1 = new CompilationUnit("a.I", 
+                     "package a; " +
+                     "public interface I<T extends Number>{}");
+          IApi fromApi = convert(I0,Number);
+          IApi toApi = convert(I1,Number);
+          IApiDelta apiDelta = compare(fromApi, toApi);
+          assertNull(apiDelta);
+    }
+    
+    @Test
+    public void compareUpperBounds1() throws IOException{
+        CompilationUnit Number = new CompilationUnit("a.Number", 
+                    "package a; " +
+                    "public class Number {}");
+         CompilationUnit I0 = new CompilationUnit("a.I", 
+                    "package a; " +
+                    "public interface I<T extends Number & java.io.Serializable>{}");
+         CompilationUnit I1 = new CompilationUnit("a.I", 
+                     "package a; " +
+                     "public interface I<T extends Number>{}");
+          IApi fromApi = convert(I0,Number);
+          IApi toApi = convert(I1,Number);
+          IApiDelta apiDelta = compare(fromApi, toApi);
+          assertNotNull(apiDelta);
+    }
+    
+    @Test
+    public void compareTypeVariables0() throws IOException{
+        CompilationUnit C0 = new CompilationUnit("a.C", 
+                    "package a; " +
+                    "public class C<T,S> {}");
+        CompilationUnit C1 = new CompilationUnit("a.C", 
+                    "package a; " +
+                    "public class C<S,T> {}");
+          IApi fromApi = convert(C0);
+          IApi toApi = convert(C1);
+          IApiDelta apiDelta = compare(fromApi, toApi);
+          assertNull(apiDelta);
+    }
+    
+    @Test
+    public void compareTypeVariables1() throws IOException{
+        CompilationUnit C0 = new CompilationUnit("a.C", 
+                    "package a; " +
+                    "public class C<T,S> {}");
+        CompilationUnit C1 = new CompilationUnit("a.C", 
+                    "package a; " +
+                    "public class C<T,S,R> {}");
+          IApi fromApi = convert(C0);
+          IApi toApi = convert(C1);
+          IApiDelta apiDelta = compare(fromApi, toApi);
+          assertNotNull(apiDelta);
+    }
+    
+    @Test
+    public void compareTypeVariables2() throws IOException{
+        CompilationUnit C0 = new CompilationUnit("a.C", 
+                    "package a; " +
+                    "public class C<T,S> {" +
+                    "  public void m(T t, S s){} " +
+                    "}");
+        CompilationUnit C1 = new CompilationUnit("a.C", 
+                    "package a; " +
+                    "public class C<S,T> {" +
+                    "  public void m(S s, T t){} " +
+                    "}");
+          IApi fromApi = convert(C0);
+          IApi toApi = convert(C1);
+          IApiDelta apiDelta = compare(fromApi, toApi);
+          assertNull(apiDelta);
+    }
+    
+    @Test
+    public void compareTypeVariables3() throws IOException{
+        CompilationUnit C0 = new CompilationUnit("a.C", 
+                    "package a; " +
+                    "public class C<T,S> {" +
+                    "  public void m(T t, S s){} " +
+                    "}");
+        CompilationUnit C1 = new CompilationUnit("a.C", 
+                    "package a; " +
+                    "public class C<S,T> {" +
+                    "  public void m(T t, S s){} " +
+                    "}");
+          IApi fromApi = convert(C0);
+          IApi toApi = convert(C1);
+          IApiDelta apiDelta = compare(fromApi, toApi);
+          assertNotNull(apiDelta);
+    }
+    
+    @Test
+    public void compareTypeVariables4() throws IOException{
+        CompilationUnit C0 = new CompilationUnit("a.C", 
+                    "package a; " +
+                    "public class C<T> {" +
+                    "  public class I{" +
+                    "    public void m(T t){}" +
+                    "  } " +
+                    "}");
+        CompilationUnit C1 = new CompilationUnit("a.C", 
+                    "package a; " +
+                    "public class C {" +
+                    "  public class I<T>{" +
+                    "    public void m(T t){}" +
+                    "  } " +
+                    "}");
+          IApi fromApi = convert(C0);
+          IApi toApi = convert(C1);
+          IApiDelta apiDelta = compare(fromApi, toApi);
+          assertNotNull(apiDelta);
+    }
+    
+    @Test
+    public void interfaceClosureTest() throws IOException{
+        CompilationUnit B = new CompilationUnit("a.B", 
+                    "package a; " +
+                    "public class  B<S> {}");
+        CompilationUnit C = new CompilationUnit("a.C", 
+                "package a; " +
+                "public class C<R> extends B<R>  {}");
+        CompilationUnit E = new CompilationUnit("a.E", 
+                "package a; " +
+                "public class E<Q> extends C<Q> {}");
+        CompilationUnit F = new CompilationUnit("a.F", 
+                "package a; " +
+                "public class F<P> extends E<P> {}");
+        CompilationUnit G = new CompilationUnit("a.G", 
+                "package a; " +
+                "public class G<O> extends F<O> {}");
+        CompilationUnit H = new CompilationUnit("a.H", 
+                "package a; " +
+                "public class H<R> extends G<R> {}");
+//        IApi fromApi = convert(B,C, E, F);
+//        IApi toApi = convert(B,C,E, F);
+          IApi fromApi = convert(B,C, E,F, G, H);
+          IApi toApi = convert(B,C,E,F, G, H);
+          
+          
+          long start = System.currentTimeMillis();
+          IApiDelta apiDelta = compare(fromApi, toApi);
+          System.out.println("compare took :" + (System.currentTimeMillis() -start) + "ms");
+          assertNull(apiDelta);
+    }
+    
+}
\ No newline at end of file
diff --git a/tools/signature-tools/test/signature/comparator/MethodCompareTests.java b/tools/signature-tools/test/signature/comparator/MethodCompareTests.java
new file mode 100644
index 0000000..3e94506
--- /dev/null
+++ b/tools/signature-tools/test/signature/comparator/MethodCompareTests.java
@@ -0,0 +1,495 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.comparator;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+import signature.comparator.util.AbstractComparatorTest;
+import signature.compare.model.IApiDelta;
+import signature.compare.model.IClassDefinitionDelta;
+import signature.compare.model.DeltaType;
+import signature.converter.util.CompilationUnit;
+import signature.model.IApi;
+
+public abstract class MethodCompareTests extends AbstractComparatorTest {
+
+    
+    @Test
+    public void compareEqualClasses() throws IOException{
+        CompilationUnit A = new CompilationUnit("a.A", 
+                      "package a; " +
+                      "public class A {" +
+                      "  public void m(){}" +
+                      "}");
+        IApi fromApi = convert(A);
+        IApi toApi = convert(A);
+        assertNull(compare(fromApi, toApi));
+    }
+      
+    @Test
+    public void compareMissingMethod() throws IOException{
+        CompilationUnit A = new CompilationUnit("a.A", 
+                      "package a; " +
+                      "public class A {" +
+                      "  public void m(){}" +
+                      "}");
+        CompilationUnit AMissing = new CompilationUnit("a.A", 
+                      "package a; " +
+                      "public class A {" +
+                      "}");
+        IApi fromApi = convert(A);
+        IApi toApi = convert(AMissing);
+        IApiDelta delta = compare(fromApi, toApi);
+        assertNotNull(delta);
+        IClassDefinitionDelta classDelta = delta.getPackageDeltas().iterator().next().getClassDeltas().iterator().next();
+        assertEquals(1, classDelta.getMethodDeltas().size());
+        assertEquals(DeltaType.REMOVED, classDelta.getMethodDeltas().iterator().next().getType());
+    }
+      
+    @Test 
+    public void compareAddedMethod() throws IOException{
+        CompilationUnit A = new CompilationUnit("a.A", 
+                  "package a; " +
+                  "public class A {" +
+                  "  public void m(){}" +
+                  "}");
+        CompilationUnit AMissing = new CompilationUnit("a.A", 
+                  "package a; " +
+                  "public class A {" +
+                  "}");
+        IApi fromApi = convert(AMissing);
+        IApi toApi = convert(A);
+        IApiDelta delta = compare(fromApi, toApi);
+        assertNotNull(delta);
+        IClassDefinitionDelta classDelta = delta.getPackageDeltas().iterator().next().getClassDeltas().iterator().next();
+        assertEquals(1, classDelta.getMethodDeltas().size());
+        assertEquals(DeltaType.ADDED, classDelta.getMethodDeltas().iterator().next().getType());
+    }
+      
+    @Test
+    public void compareChangedMethod() throws IOException{
+        CompilationUnit A = new CompilationUnit("a.A", 
+                  "package a; " +
+                  "public class A {" +
+                  "  public void m(){}" +
+                  "}");
+        CompilationUnit AMissing = new CompilationUnit("a.A", 
+                  "package a; " +
+                  "public class A {" +
+                  "  public void m() throws Exception {}" +
+                  "}");
+        IApi fromApi = convert(AMissing);
+        IApi toApi = convert(A);
+        IApiDelta delta = compare(fromApi, toApi);
+        assertNotNull(delta);
+        IClassDefinitionDelta classDelta = delta.getPackageDeltas().iterator().next().getClassDeltas().iterator().next();
+        assertEquals(1, classDelta.getMethodDeltas().size());
+        assertEquals(DeltaType.CHANGED, classDelta.getMethodDeltas().iterator().next().getType());
+    }
+      
+    @Test
+    public void compareAddedParameterMethod() throws IOException{
+        CompilationUnit A = new CompilationUnit("a.A", 
+                  "package a; " +
+                  "public class A {" +
+                  "  public void m(){}" +
+                  "}");
+        CompilationUnit AMissing = new CompilationUnit("a.A", 
+                  "package a; " +
+                  "public class A {" +
+                  "  public void m(int i) {}" +
+                  "}");
+        IApi fromApi = convert(AMissing);
+        IApi toApi = convert(A);
+        IApiDelta delta = compare(fromApi, toApi);
+        assertNotNull(delta);
+        IClassDefinitionDelta classDelta = delta.getPackageDeltas().iterator().next().getClassDeltas().iterator().next();
+        assertEquals(2, classDelta.getMethodDeltas().size()); //one added , one removed
+    }
+      
+    @Test
+    public void compareExceptions0() throws IOException{
+        CompilationUnit E0 = new CompilationUnit("a.E0", 
+                "package a; " +
+                "public class E0 extends Exception {}");
+        CompilationUnit E1 = new CompilationUnit("a.E1", 
+                "package a; " +
+                "public class E1 extends E0 {}");
+        CompilationUnit C0 = new CompilationUnit("a.C0", 
+                 "package a; " +
+                 "public class C0 {" +
+                 "  public void m() throws E0 {}" +
+                 "}");
+        CompilationUnit C0_E1 = new CompilationUnit("a.C0", 
+                 "package a; " +
+                 "public class C0{" +
+                 "  public void m() throws E0, E1 {}" +
+                 "}");
+        IApi fromApi = convert(E0, E1, C0);
+        IApi toApi = convert(E0, E1, C0_E1);
+        IApiDelta apiDelta = compare(fromApi, toApi);
+        assertNull(apiDelta);
+    }
+    
+    @Test
+    public void compareExceptions1() throws IOException{
+        CompilationUnit E0 = new CompilationUnit("a.E0", 
+                "package a; " +
+                "public class E0 extends Exception {}");
+        CompilationUnit E1 = new CompilationUnit("a.E1", 
+                "package a; " +
+                "public class E1 extends Exception {}");
+        CompilationUnit C0 = new CompilationUnit("a.C0", 
+                 "package a; " +
+                 "public class C0 {" +
+                 "  public void m() throws E0 {}" +
+                 "}");
+        CompilationUnit C0_E1 = new CompilationUnit("a.C0", 
+                 "package a; " +
+                 "public class C0{" +
+                 "  public void m() throws E0, E1 {}" +
+                 "}");
+        IApi fromApi = convert(E0, E1, C0);
+        IApi toApi = convert(E0, E1, C0_E1);
+        IApiDelta apiDelta = compare(fromApi, toApi);
+        assertNotNull(apiDelta);
+    }
+    
+    @Test
+    public void compareRuntimeExceptions() throws IOException{
+        CompilationUnit E0 = new CompilationUnit("a.E0", 
+                 "package a; " +
+                 "public class E0 extends RuntimeException {}");
+        CompilationUnit C0 = new CompilationUnit("a.C0", 
+                 "package a; " +
+                 "public class C0{" +
+                 "  public void m() {}" +
+                 "}");
+        CompilationUnit C0_E0 = new CompilationUnit("a.C0", 
+                 "package a; " +
+                 "public class C0 {" +
+                 "  public void m() throws E0 {}" +
+                 "}");
+        IApi fromApi = convert(E0, C0);
+        IApi toApi = convert(E0, C0_E0);
+        IApiDelta apiDelta = compare(fromApi, toApi);
+        assertNull(apiDelta);
+    }
+    
+    @Test
+    public void compareAnnotations() throws IOException{
+        CompilationUnit C0 = new CompilationUnit("a.C0", 
+                 "package a; " +
+                 "public class C0{" +
+                 "  public void m(int i) {}" +
+                 "}");
+        CompilationUnit C1 = new CompilationUnit("a.C0", 
+                 "package a; " +
+                 "public class C0 {" +
+                 "  public void m(@Deprecated  int i) {}" +
+                 "}");
+        IApi fromApi = convert(C0);
+        IApi toApi = convert(C1);
+        IApiDelta apiDelta = compare(fromApi, toApi);
+        assertNotNull(apiDelta);
+    }
+    
+    @Test
+    public void compareMissingDefaultConstructor() throws IOException{
+        CompilationUnit C0 = new CompilationUnit("a.C0", 
+                 "package a; " +
+                 "public class C0{" +
+                 "  public C0() {}" +
+                 "}");
+        CompilationUnit C1 = new CompilationUnit("a.C0", 
+                 "package a; " +
+                 "public class C0 {}");
+        IApi fromApi = convert(C0);
+        IApi toApi = convert(C1);
+        IApiDelta apiDelta = compare(fromApi, toApi);
+        assertNull(apiDelta);
+    }
+        
+    @Test
+    public void compareMissingAbstractMethod() throws IOException{
+        CompilationUnit I = new CompilationUnit("a.I", 
+                 "package a; " +
+                 "public interface I{" +
+                 "  void m();" + 
+                   "}");
+        CompilationUnit C0 = new CompilationUnit("a.C0", 
+                 "package a; " +
+                 "public abstract class C0 implements I{" +
+                 "  public abstract void m(); " +
+                 "}");
+        CompilationUnit C1 = new CompilationUnit("a.C0", 
+                 "package a; " +
+                 "public abstract class C0 implements I{}");
+        IApi fromApi = convert(C0, I);
+        IApi toApi = convert(C1, I);
+        IApiDelta apiDelta = compare(fromApi, toApi);
+        assertNull(apiDelta);
+    }
+           
+    @Test
+    public void compareMissingInheritedMethod() throws IOException{
+        CompilationUnit I = new CompilationUnit("a.I", 
+                "package a; " +
+                "public class I{" +
+                "  public void m(){};" + 
+                "}");
+        CompilationUnit C0 = new CompilationUnit("a.C0", 
+                "package a; " +
+                "public class C0 extends I{" +
+                "  public void m(){}; " +
+                "}");
+        CompilationUnit C1 = new CompilationUnit("a.C0", 
+                "package a; " +
+                "public class C0 extends I{}");
+        IApi fromApi = convert(C0, I);
+        IApi toApi = convert(C1, I);
+        IApiDelta apiDelta = compare(fromApi, toApi);
+        assertNull(apiDelta);
+     }
+       
+    @Test
+    public void compareMissingInheritedMethodGeneric0() throws IOException{
+        CompilationUnit I = new CompilationUnit("a.I", 
+                "package a; " +
+                "public class I<T>{" +
+                "  public void m(T t){};" + 
+                "}");
+        CompilationUnit C0 = new CompilationUnit("a.C0", 
+                "package a; " +
+                "public class C0<T> extends I<T>{" +
+                "  public void m(T t){}; " +
+                "}");
+        CompilationUnit C1 = new CompilationUnit("a.C0", 
+                "package a; " +
+                "public class C0<T> extends I<T>{}");
+        IApi fromApi = convert(C0, I);
+        IApi toApi = convert(C1, I);
+        IApiDelta apiDelta = compare(fromApi, toApi);
+        assertNull(apiDelta);
+    }
+           
+    @Test
+    public void compareMissingInheritedMethodGeneric1() throws IOException{
+        CompilationUnit I = new CompilationUnit("a.I", 
+                "package a; " +
+                "public class I<T,S>{" +
+                "  public void m(S s){};" + 
+                "}");
+        CompilationUnit C0 = new CompilationUnit("a.C0", 
+                "package a; " +
+                "public class C0<Q, R> extends I<Q,R>{" +
+                "  public void m(R t){}; " +
+                "}");
+        CompilationUnit C1 = new CompilationUnit("a.C0", 
+                "package a; " +
+                "public class C0<Y,Z> extends I<Y,Z>{}");
+         IApi fromApi = convert(C0, I);
+         IApi toApi = convert(C1, I);
+         IApiDelta apiDelta = compare(fromApi, toApi);
+         assertNull(apiDelta);
+    }
+           
+    @Test
+    public void compareMissingInheritedMethodGeneric2() throws IOException{
+        CompilationUnit I = new CompilationUnit("a.I", 
+                "package a; " +
+                "public class I<T,S>{" +
+                "  public void m(S s){};" + 
+                "}");
+        CompilationUnit J = new CompilationUnit("a.J", 
+                "package a; " +
+                "public class J<W> extends I<Number,W>{" +
+                "  public void m(W w){};" + 
+                "}");
+        CompilationUnit C0 = new CompilationUnit("a.C0", 
+                "package a; " +
+                "public class C0<Q> extends J<Q>{" +
+                "  public void m(Q t){}; " +
+                "}");
+        CompilationUnit C1 = new CompilationUnit("a.C0", 
+                "package a; " +
+                "public class C0<Y> extends J<Y>{}");
+        IApi fromApi = convert(C0, I, J);
+        IApi toApi = convert(C1, I, J);
+        IApiDelta apiDelta = compare(fromApi, toApi);
+        assertNull(apiDelta);
+    }
+    
+    
+
+    @Test
+    public void compareMissingInheritedMethodGeneric3() throws IOException{
+        CompilationUnit Q = new CompilationUnit("a.Q", 
+                "package a; " +
+                "public class Q<S,T>{ " +
+                "  public void m(T s){} " +
+                "}");
+        
+        CompilationUnit W = new CompilationUnit("a.W", 
+                "package a; " +
+                "public class W<A,B> extends Q<A,A>{}");
+        CompilationUnit E0 = new CompilationUnit("a.E", 
+                "package a; " +
+                "public class E<C,D> extends W<C,C>{" +
+                "  public void m(C s){}" +
+                "}");
+        CompilationUnit E1 = new CompilationUnit("a.E", 
+                "package a; " +
+                "public class E<C,D> extends W<C,C>{}");
+        IApi fromApi = convert(E0, Q, W);
+        IApi toApi = convert(E1, Q, W);
+        IApiDelta apiDelta = compare(fromApi, toApi);
+        assertNull(apiDelta);
+    }
+    
+    @Test
+    public void compareMissingInheritedMethodGeneric4() throws IOException{
+        CompilationUnit Q = new CompilationUnit("a.Q", 
+                "package a; " +
+                "public class Q<S,T>{ " +
+                "  public void m(T t, S s){} " +
+                "}");
+        
+        CompilationUnit W = new CompilationUnit("a.W", 
+                "package a; " +
+                "public class W<A,B> extends Q<A,A>{}");
+        CompilationUnit E0 = new CompilationUnit("a.E", 
+                "package a; " +
+                "public class E<C,D> extends W<C,C>{" +
+                "  public void m(C s, C c){}" +
+                "}");
+        CompilationUnit E1 = new CompilationUnit("a.E", 
+                "package a; " +
+                "public class E<C,D> extends W<C,C>{}");
+        IApi fromApi = convert(E0, Q, W);
+        IApi toApi = convert(E1, Q, W);
+        IApiDelta apiDelta = compare(fromApi, toApi);
+        assertNull(apiDelta);
+    }
+    
+    @Test
+    public void compareMissingInheritedMethodGeneric5() throws IOException{
+        CompilationUnit Q = new CompilationUnit("a.Q", 
+                "package a; " +
+                "public class Q{}");
+        
+        CompilationUnit I = new CompilationUnit("a.I", 
+                "package a; " +
+                "public class I<S,T>{" +
+                "  public void m(T s){};" + 
+                "}");
+        CompilationUnit C0 = new CompilationUnit("a.C0", 
+                "package a; " +
+                "public class C0<P> extends I<P, Q>{" +
+                "  public void m(Q t){}; " +
+                "}");
+        CompilationUnit C1 = new CompilationUnit("a.C0", 
+                "package a; " +
+                "public class C0<Y> extends I<Y, Q>{}");
+        IApi fromApi = convert(C0, I, Q);
+        IApi toApi = convert(C1, I, Q);
+        IApiDelta apiDelta = compare(fromApi, toApi);
+        assertNull(apiDelta);
+    }
+    
+    
+    @Test
+    public void substitutionTest() throws IOException{
+        CompilationUnit NUMBER = new CompilationUnit("a.Number", 
+                "package a; " +
+                "public class Number{}");
+        CompilationUnit Q = new CompilationUnit("a.A", 
+                "package a; " +
+                "public class A<T>{ " +
+                "  public void m(T t){} " +
+                "}");
+        CompilationUnit E0 = new CompilationUnit("a.E", 
+                "package a; " +
+                "public class E extends A<Number>{" +
+                "  public void m(Number n){}" +
+                "}");
+        CompilationUnit E1 = new CompilationUnit("a.E", 
+                "package a; " +
+                "public class E extends A<Number>{}");
+        IApi fromApi = convert(E0, Q, NUMBER);
+        IApi toApi = convert(E1, Q, NUMBER);
+        
+        IApiDelta apiDelta = compare(fromApi, toApi);
+        assertNull(apiDelta);
+    }
+    
+    @Test
+    public void substitutionArrayTest() throws IOException{
+        CompilationUnit NUMBER = new CompilationUnit("a.Number", 
+                "package a; " +
+                "public class Number{}");
+        CompilationUnit Q = new CompilationUnit("a.A", 
+                "package a; " +
+                "public class A<T>{ " +
+                "  public void m(T[] t){} " +
+                "}");
+        CompilationUnit E0 = new CompilationUnit("a.E", 
+                "package a; " +
+                "public class E extends A<Number>{" +
+                "  public void m(Number[] n){}" +
+                "}");
+        CompilationUnit E1 = new CompilationUnit("a.E", 
+                "package a; " +
+                "public class E extends A<Number>{}");
+        IApi fromApi = convert(E0, Q, NUMBER);
+        IApi toApi = convert(E1, Q, NUMBER);
+        
+        IApiDelta apiDelta = compare(fromApi, toApi);
+        assertNull(apiDelta);
+    }
+    
+    @Test
+    public void substitutionNestedTypes() throws IOException{
+        CompilationUnit NUMBER = new CompilationUnit("a.Number", 
+                "package a; " +
+                "public class Number{}");
+        CompilationUnit Q = new CompilationUnit("a.A", 
+                "package a; " +
+                "public class A<T>{ " +
+                "  public void m(A<A<T[]>> t){} " +
+                "}");
+        CompilationUnit E0 = new CompilationUnit("a.E", 
+                "package a; " +
+                "public class E extends A<Number>{" +
+                "  public void m(A<A<Number[]>> n){}" +
+                "}");
+        CompilationUnit E1 = new CompilationUnit("a.E", 
+                "package a; " +
+                "public class E extends A<Number>{}");
+        IApi fromApi = convert(E0, Q, NUMBER);
+        IApi toApi = convert(E1, Q, NUMBER);
+        
+        IApiDelta apiDelta = compare(fromApi, toApi);
+        assertNull(apiDelta);
+    }
+}
diff --git a/tools/signature-tools/test/signature/comparator/PackageCompareTest.java b/tools/signature-tools/test/signature/comparator/PackageCompareTest.java
new file mode 100644
index 0000000..d522186
--- /dev/null
+++ b/tools/signature-tools/test/signature/comparator/PackageCompareTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.comparator;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+
+import signature.comparator.util.AbstractComparatorTest;
+import signature.compare.model.IApiDelta;
+import signature.compare.model.DeltaType;
+import signature.compare.model.IPackageDelta;
+import signature.converter.util.CompilationUnit;
+import signature.model.IApi;
+
+import java.io.IOException;
+
+public abstract class PackageCompareTest extends AbstractComparatorTest{
+
+    @Test
+    public void compareEqualPackageTest0() throws IOException{
+         CompilationUnit from = new CompilationUnit("a.A", 
+                    "package a; " +
+                    "public class A {}");
+          IApi fromApi = convert(from);
+          IApi toApi = convert(from);
+          IApiDelta delta = compare(fromApi, toApi);
+          assertNull(delta);
+    }
+
+    @Test
+    public void compareEqualPackageTest1() throws IOException{
+         CompilationUnit from0 = new CompilationUnit("a.A", 
+                    "package a; " +
+                    "public class A {}");
+         CompilationUnit from1 = new CompilationUnit("a.b.A", 
+                    "package a.b; " +
+                    "public class A {}");
+          IApi fromApi = convert(from0, from1);
+          IApi toApi = convert(from0, from1);
+          assertNull(compare(fromApi, toApi));
+    }
+
+    @Test
+    public void compareRemovedPackagePackageTest1() throws IOException{
+         CompilationUnit packageA = new CompilationUnit("a.A", 
+                    "package a; " +
+                    "public class A {}");
+         CompilationUnit packageB = new CompilationUnit("a.b.A", 
+                    "package a.b; " +
+                    "public class A {}");
+          IApi fromApi = convert(packageA, packageB);
+          IApi toApi = convert(packageA);
+          IApiDelta apiDelta = compare(fromApi, toApi);
+          assertNotNull(apiDelta);
+          
+          assertEquals(1, apiDelta.getPackageDeltas().size());
+          IPackageDelta packageDelta = apiDelta.getPackageDeltas().iterator().next();
+          assertEquals(DeltaType.REMOVED, packageDelta.getType());
+    }
+
+    @Test
+    public void compareAddedPackagePackageTest1() throws IOException{
+         CompilationUnit packageA = new CompilationUnit("a.A", 
+                    "package a; " +
+                    "public class A {}");
+         CompilationUnit packageB = new CompilationUnit("a.b.A", 
+                    "package a.b; " +
+                    "public class A {}");
+          IApi fromApi = convert(packageA);
+          IApi toApi = convert(packageA, packageB);
+          IApiDelta apiDelta = compare(fromApi, toApi);
+          assertNotNull(apiDelta);
+          
+          assertEquals(1, apiDelta.getPackageDeltas().size());
+          IPackageDelta packageDelta = apiDelta.getPackageDeltas().iterator().next();
+          assertEquals(DeltaType.ADDED, packageDelta.getType());
+    }
+}
diff --git a/tools/signature-tools/test/signature/comparator/util/AbstractComparatorTest.java b/tools/signature-tools/test/signature/comparator/util/AbstractComparatorTest.java
new file mode 100644
index 0000000..6392dc9
--- /dev/null
+++ b/tools/signature-tools/test/signature/comparator/util/AbstractComparatorTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.comparator.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Before;
+
+import signature.compare.ApiComparator;
+import signature.compare.IApiComparator;
+import signature.compare.model.IApiDelta;
+import signature.compare.model.IClassDefinitionDelta;
+import signature.compare.model.IPackageDelta;
+import signature.converter.util.AbstractConvertTest;
+import signature.model.IApi;
+public abstract class AbstractComparatorTest extends AbstractConvertTest{
+
+    private IApiComparator comparator;
+
+    @Before
+    public void setupComparator() {
+        comparator = new ApiComparator();
+    }
+    
+    public IApiDelta compare(IApi from, IApi to){
+        return comparator.compare(from, to);
+    }
+
+    public IPackageDelta getSinglePackageDelta(IApiDelta apiDelta){
+        assertNotNull(apiDelta);
+        assertEquals(1, apiDelta.getPackageDeltas().size());
+        return apiDelta.getPackageDeltas().iterator().next();
+    }
+    
+    public IClassDefinitionDelta getSingleClassDelta(IApiDelta apiDelta){
+        IPackageDelta packageDelta = getSinglePackageDelta(apiDelta);
+        assertEquals(1, packageDelta.getClassDeltas().size());
+        return packageDelta.getClassDeltas().iterator().next();
+    }
+
+}
diff --git a/tools/signature-tools/test/signature/converter/AllDexTests.java b/tools/signature-tools/test/signature/converter/AllDexTests.java
new file mode 100644
index 0000000..84d26a8
--- /dev/null
+++ b/tools/signature-tools/test/signature/converter/AllDexTests.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+import signature.converter.dex.DexTestConverter;
+import signature.converter.util.ITestSourceConverter;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    AllDexTests.ClassTest.class,
+    AllDexTests.PackageTest.class,
+    AllDexTests.AnnotationTest.class,
+    AllDexTests.VisibilityTest.class,
+    AllDexTests.WildcardTest.class,
+    AllDexTests.EnumTest.class
+})
+public class AllDexTests {
+    private static ITestSourceConverter newConverter(){
+        return new DexTestConverter();
+    }
+    
+    public static class ClassTest extends ConvertClassTest {
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+    public static class AnnotationTest extends ConvertAnnotationTest {
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+    public static class PackageTest extends ConvertPackageTest {
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+    public static class VisibilityTest extends ConvertVisibilityTest {
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+    
+    public static class WildcardTest extends ConvertWildcardTest {
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+    
+    public static class EnumTest extends ConvertEnumTest {
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+    
+    public static class ParameterizedTypeTest extends ConvertParameterizedTypeTest {
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+}
+
diff --git a/tools/signature-tools/test/signature/converter/AllDocletTests.java b/tools/signature-tools/test/signature/converter/AllDocletTests.java
new file mode 100644
index 0000000..610917e
--- /dev/null
+++ b/tools/signature-tools/test/signature/converter/AllDocletTests.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+import signature.converter.doclet.DocletTestConverter;
+import signature.converter.util.ITestSourceConverter;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    AllDocletTests.ClassTest.class,
+    AllDocletTests.PackageTest.class,
+    AllDocletTests.AnnotationTest.class,
+    AllDocletTests.VisibilityTest.class,
+    AllDocletTests.WildcardTest.class,
+    AllDocletTests.EnumTest.class
+})
+public class AllDocletTests {
+    private static ITestSourceConverter newConverter(){
+        return new DocletTestConverter();
+    }
+    
+    public static class ClassTest extends ConvertClassTest {
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+    public static class AnnotationTest extends ConvertAnnotationTest {
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+    public static class PackageTest extends ConvertPackageTest {
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+    public static class VisibilityTest extends ConvertVisibilityTest {
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+    public static class WildcardTest extends ConvertWildcardTest {
+        @Override
+        public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+    public static class EnumTest extends ConvertEnumTest {
+        @Override public ITestSourceConverter createConverter() {
+            return newConverter();
+        }
+    }
+}
+
diff --git a/tools/signature-tools/test/signature/converter/ConvertAnnotationTest.java b/tools/signature-tools/test/signature/converter/ConvertAnnotationTest.java
new file mode 100644
index 0000000..f53f403
--- /dev/null
+++ b/tools/signature-tools/test/signature/converter/ConvertAnnotationTest.java
@@ -0,0 +1,761 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * 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 signature.converter;

+

+import static org.junit.Assert.assertEquals;

+import static org.junit.Assert.assertSame;

+import static org.junit.Assert.assertTrue;

+

+import java.io.IOException;

+import java.util.Set;

+

+import org.junit.Test;

+

+import signature.converter.util.AbstractConvertTest;

+import signature.converter.util.CompilationUnit;

+import signature.model.IAnnotation;

+import signature.model.IAnnotationField;

+import signature.model.IApi;

+import signature.model.IArrayType;

+import signature.model.IClassDefinition;

+import signature.model.IClassReference;

+import signature.model.IEnumConstant;

+import signature.model.IPackage;

+import signature.model.IPrimitiveType;

+import signature.model.ITypeReference;

+import signature.model.Kind;

+import signature.model.impl.SigClassReference;

+import signature.model.impl.SigPrimitiveType;

+import signature.model.util.ModelUtil;

+

+public abstract class ConvertAnnotationTest extends AbstractConvertTest {

+

+    // Tests whether an annotation declaration element may be annotated with 

+    // the declared annotation.

+    @Test

+    public void convertAnnotationDefinition1() throws IOException {

+        CompilationUnit classSrc = new CompilationUnit("a.ToDo", 

+                "package a; " +

+                "public @interface ToDo {" +

+                "    @ToDo(name=\"ToDo\")" +

+                "   String name() default \"nobody\";" +

+                "}");

+        IApi api = convert(classSrc);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "ToDo");

+        assertTrue(sigClass.getKind() == Kind.ANNOTATION);

+        assertEquals(0, sigClass.getConstructors().size());

+        assertEquals(0, sigClass.getMethods().size());

+        assertEquals(0, sigClass.getFields().size());

+        Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField field = annotationFields.iterator().next();

+        assertEquals("name", field.getName());

+        assertEquals("String", ((IClassReference)field.getType()).getClassDefinition().getName());

+        assertEquals("nobody", field.getDefaultValue());

+        Set<IAnnotation> annotations = field.getAnnotations();

+        assertEquals(1, annotations.size());

+        IAnnotation annotation = annotations.iterator().next();

+        assertSame(sigClass, annotation.getType().getClassDefinition());

+        // TODO TEST add additional assert for annotation.getElements()

+    }

+

+    // Tests whether an annotation declaration may be annotated with 

+    // the declared annotation.

+    @Test

+    public void convertAnnotationDefinition2() throws IOException {

+        CompilationUnit classSrc = new CompilationUnit("a.ToDo", 

+                "package a; " +

+                "@ToDo\n" +

+                "public @interface ToDo {" +

+                "   String name() default \"nobody\";" +

+                "}");

+        IApi api = convert(classSrc);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "ToDo");

+        assertTrue(sigClass.getKind() == Kind.ANNOTATION);

+        assertEquals(0, sigClass.getConstructors().size());

+        assertEquals(0, sigClass.getMethods().size());

+        assertEquals(0, sigClass.getFields().size());

+        Set<IAnnotation> annotations = sigClass.getAnnotations();

+        assertEquals(1, annotations.size());

+        IAnnotation annotation = annotations.iterator().next();

+        assertSame(sigClass, ((SigClassReference)annotation.getType()).getClassDefinition());

+        assertEquals(0, annotation.getElements().size());

+    }

+

+    @Test

+    public void convertAnnotationDefinition3() throws IOException {

+        CompilationUnit classSrc = new CompilationUnit("a.ToDo", 

+                "package a; " +

+                "public @interface ToDo {" +

+                "   String name() default \"nobody\";" +

+                "   int num() default 3;" +

+                "}");

+        IApi api = convert(classSrc);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "ToDo");

+        assertTrue(sigClass.getKind() == Kind.ANNOTATION);

+        assertEquals(0, sigClass.getConstructors().size());

+        assertEquals(0, sigClass.getMethods().size());

+        assertEquals(0, sigClass.getFields().size());

+        Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();

+        assertEquals(2, annotationFields.size());

+        IAnnotationField name = ModelUtil.getAnnotationField(sigClass, "name");

+        IAnnotationField num = ModelUtil.getAnnotationField(sigClass, "num");

+        

+        assertEquals("name", name.getName());

+        assertEquals("num", num.getName());

+        

+        assertEquals("nobody", name.getDefaultValue());

+        assertEquals(3, num.getDefaultValue());

+    }

+    

+    

+    // tests whether default int value has the correct type and defaultValue

+    @Test

+    public void testAnnotationDefaultsInt1() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.A", 

+                "package a; " +

+                "public @interface A {" +

+                "    int value() default 1;" +

+                "}");

+        IApi api = convert(src);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(sigClass.getKind() == Kind.ANNOTATION);

+        Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField annotationField = annotationFields.iterator().next();

+        assertEquals("value", annotationField.getName());

+        assertTrue(annotationField.getType() instanceof IPrimitiveType);

+        IPrimitiveType annotationFieldType = (IPrimitiveType)annotationField.getType();

+        assertSame(SigPrimitiveType.INT_TYPE, annotationFieldType);

+        

+        assertTrue(annotationField.getDefaultValue() instanceof Integer);

+        Integer defaultValue = (Integer)annotationField.getDefaultValue();

+        assertEquals(1, defaultValue.intValue());

+    }

+

+    // tests whether default int[] value has the correct type and defaultValue

+    @Test

+    public void testAnnotationDefaultsInt2() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.A", 

+                "package a; " +

+                "public @interface A {" +

+                "    int[] value() default {};" +

+                "}");

+        IApi api = convert(src);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(sigClass.getKind() == Kind.ANNOTATION);

+        Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField field = annotationFields.iterator().next();

+        assertEquals("value", field.getName());

+        

+        assertTrue(field.getType() instanceof IArrayType);

+        assertTrue(field.getDefaultValue() instanceof Object[]);

+        assertSame(field.getDefaultValue().getClass(), Object[].class);

+        Object[] defaultValue = (Object[])field.getDefaultValue();

+        assertEquals(0, defaultValue.length);

+    }

+

+    // tests whether default int[] value has the correct type and defaultValue

+    @Test

+    public void testAnnotationDefaultsInt3() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.A", 

+                "package a; " +

+                "public @interface A {" +

+                "    int[] value() default {1,2};" +

+                "}");

+        IApi api = convert(src);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(sigClass.getKind() == Kind.ANNOTATION);

+        Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField field = annotationFields.iterator().next();

+        assertEquals("value", field.getName());

+        

+        assertTrue(field.getType() instanceof IArrayType);

+        assertTrue(field.getDefaultValue() instanceof Object[]);

+        assertSame(field.getDefaultValue().getClass(), Object[].class);

+        Object[] defaultValue = (Object[])field.getDefaultValue();

+        assertEquals(2, defaultValue.length);

+        

+        Object defaultValue0 = defaultValue[0];

+        assertTrue(defaultValue0 instanceof Integer);

+        Integer defaultValue0int = (Integer)defaultValue0;

+        assertEquals(1, defaultValue0int.intValue());

+

+        Object defaultValue1 = defaultValue[1];

+        assertTrue(defaultValue1 instanceof Integer);

+        Integer defaultValue1int = (Integer)defaultValue1;

+        assertEquals(2, defaultValue1int.intValue());

+    }

+

+

+    // tests whether default double value has the correct type and defaultValue

+    @Test

+    public void testAnnotationDefaultsDouble1() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.A", 

+                "package a; " +

+                "public @interface A {" +

+                "    double value() default 1;" +

+                "}");

+        IApi api = convert(src);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(sigClass.getKind() == Kind.ANNOTATION);

+        Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField annotationField = annotationFields.iterator().next();

+        assertEquals("value", annotationField.getName());

+        assertTrue(annotationField.getType() instanceof IPrimitiveType);

+        IPrimitiveType annotationFieldType = (IPrimitiveType)annotationField.getType();

+        assertSame(SigPrimitiveType.DOUBLE_TYPE, annotationFieldType);

+        

+        

+        assertTrue(annotationField.getDefaultValue() instanceof Double);

+        Double defaultValue = (Double)annotationField.getDefaultValue();

+        assertEquals(1.0, defaultValue.doubleValue());

+    }

+

+    // tests whether default int[] value has the correct type and defaultValue

+    @Test

+    public void testAnnotationDefaultsDouble2() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.A", 

+                "package a; " +

+                "public @interface A {" +

+                "    double[] value() default {};" +

+                "}");

+        IApi api = convert(src);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(sigClass.getKind() == Kind.ANNOTATION);

+        Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField field = annotationFields.iterator().next();

+        assertEquals("value", field.getName());

+        

+        assertTrue(field.getType() instanceof IArrayType);

+        assertTrue(field.getDefaultValue() instanceof Object[]);

+        assertSame(field.getDefaultValue().getClass(), Object[].class);

+        Object[] defaultValue = (Object[])field.getDefaultValue();

+        assertEquals(0, defaultValue.length);

+    }

+

+    // tests whether default int[] value has the correct type and defaultValue

+    @Test

+    public void testAnnotationDefaultsDouble3() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.A", 

+                "package a; " +

+                "public @interface A {" +

+                "    double[] value() default {1,2.5};" +

+                "}");

+        IApi api = convert(src);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(sigClass.getKind() == Kind.ANNOTATION);

+        Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField field = annotationFields.iterator().next();

+        assertEquals("value", field.getName());

+        

+        assertTrue(field.getType() instanceof IArrayType);

+        assertTrue(field.getDefaultValue() instanceof Object[]);

+        assertSame(field.getDefaultValue().getClass(), Object[].class);

+        Object[] defaultValue = (Object[])field.getDefaultValue();

+        assertEquals(2, defaultValue.length);

+        

+        Object defaultValue0 = defaultValue[0];

+        assertTrue(defaultValue0 instanceof Double);

+        Double defaultValue0int = (Double)defaultValue0;

+        assertEquals(1, defaultValue0int.doubleValue());

+

+        Object defaultValue1 = defaultValue[1];

+        assertTrue(defaultValue1 instanceof Double);

+        Double defaultValue1int = (Double)defaultValue1;

+        assertEquals(2.5, defaultValue1int.doubleValue());

+    }

+

+

+    // tests whether default enum value has the correct type

+    @Test

+    public void testAnnotationDefaultsEnum1() throws IOException {

+        CompilationUnit src1 = new CompilationUnit("a.A", 

+                "package a; " +

+                "public @interface A {" +

+                "    Kind value() default Kind.TWO;" +

+                "}");

+        CompilationUnit src2 = new CompilationUnit("a.Kind", 

+                "package a; " +

+                "public enum Kind {" +

+                "    ONE, TWO, THREE" +

+                "}");

+        IApi api = convert(src1, src2);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(sigClass.getKind() == Kind.ANNOTATION);

+        Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField field = annotationFields.iterator().next();

+        assertEquals("value", field.getName());

+        assertEquals("Kind", ((IClassReference)field.getType()).getClassDefinition().getName());

+        assertTrue(field.getDefaultValue() instanceof IEnumConstant);

+        IEnumConstant defaultValue = (IEnumConstant)field.getDefaultValue();

+//        assertEquals(1, defaultValue.getOrdinal());

+        assertEquals("TWO", defaultValue.getName());

+        

+        IClassDefinition enumClass = ModelUtil.getClass(sigPackage, "Kind");

+        assertTrue(enumClass.getKind() == Kind.ENUM);

+        IEnumConstant enumTWO = null;

+        Set<IEnumConstant> enumConstants = enumClass.getEnumConstants();

+        for(IEnumConstant c : enumConstants){

+            if("TWO".equals(c.getName())) enumTWO = c;

+        }

+        assertSame(enumTWO, defaultValue);

+    }

+

+    // tests whether default enum value has the correct type

+    @Test

+    public void testAnnotationDefaultsEnum2() throws IOException {

+        CompilationUnit src1 = new CompilationUnit("a.A", 

+                "package a; " +

+                "public @interface A {" +

+                "    Kind[] value() default {};" +

+                "}");

+        CompilationUnit src2 = new CompilationUnit("a.Kind", 

+                "package a; " +

+                "public enum Kind {" +

+                "    ONE, TWO, THREE" +

+                "}");

+        IApi api = convert(src1, src2);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(sigClass.getKind() == Kind.ANNOTATION);

+        Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField field = annotationFields.iterator().next();

+        assertEquals("value", field.getName());

+        assertTrue(field.getType() instanceof IArrayType);

+        assertTrue(field.getDefaultValue() instanceof Object[]);

+        assertSame(field.getDefaultValue().getClass(), Object[].class);

+        Object[] defaultValue = (Object[])field.getDefaultValue();

+        assertEquals(0, defaultValue.length);

+    }

+

+    // tests whether default enum value has the correct type

+    @Test

+    public void testAnnotationDefaultsEnum3() throws IOException {

+        CompilationUnit src1 = new CompilationUnit("a.A", 

+                "package a; " +

+                "public @interface A {" +

+                "    Kind[] value() default {Kind.ONE,Kind.TWO};" +

+                "}");

+        CompilationUnit src2 = new CompilationUnit("a.Kind", 

+                "package a; " +

+                "public enum Kind {" +

+                "    ONE, TWO, THREE" +

+                "}");

+        IApi api = convert(src1, src2);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(sigClass.getKind() == Kind.ANNOTATION);

+        

+        Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField field = annotationFields.iterator().next();

+        assertEquals("value", field.getName());

+        

+        assertTrue(field.getType() instanceof IArrayType);

+        assertTrue(field.getDefaultValue() instanceof Object[]);

+        assertSame(field.getDefaultValue().getClass(), Object[].class);

+        Object[] defaultValue = (Object[])field.getDefaultValue();

+        assertEquals(2, defaultValue.length);

+        

+        IClassDefinition enumClass = ModelUtil.getClass(sigPackage, "Kind");

+        assertTrue(enumClass.getKind() == Kind.ENUM);

+        IEnumConstant enumONE = null;

+        IEnumConstant enumTWO = null;

+        Set<IEnumConstant> enumConstants = enumClass.getEnumConstants();

+        for(IEnumConstant c : enumConstants){

+            if("ONE".equals(c.getName())) enumONE = c;

+            if("TWO".equals(c.getName())) enumTWO = c;

+        }

+

+        Object defaultValue0 = defaultValue[0];

+        assertTrue(defaultValue0 instanceof IEnumConstant);

+        IEnumConstant defaultValue0enum = (IEnumConstant)defaultValue0;

+//        assertEquals(0, defaultValue0enum.getOrdinal());

+        assertEquals("ONE", defaultValue0enum.getName());

+        assertSame(enumONE, defaultValue0enum);

+

+        Object defaultValue1 = defaultValue[1];

+        assertTrue(defaultValue1 instanceof IEnumConstant);

+        IEnumConstant defaultValue1enum = (IEnumConstant)defaultValue1;

+//        assertEquals(1, defaultValue1enum.getOrdinal());

+        assertEquals("TWO", defaultValue1enum.getName());

+        assertSame(enumTWO, defaultValue1enum);

+    }

+

+    

+    @Test

+    public void testAnnotationDefaultsAnnotation1() throws IOException {

+        CompilationUnit src1 = new CompilationUnit("a.A", 

+                "package a; " +

+                "public @interface A {" +

+                "    AA aa() default @AA;" +

+                "}");

+        CompilationUnit src2 = new CompilationUnit("a.AA", 

+                "package a; " +

+                "public @interface AA {}");

+        IApi api = convert(src1, src2);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(sigClass.getKind() == Kind.ANNOTATION);

+        Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField field = annotationFields.iterator().next();

+        assertEquals("aa", field.getName());

+        IClassReference fieldType = (IClassReference)field.getType();

+        assertEquals("AA", fieldType.getClassDefinition().getName());

+        

+        IClassDefinition aaType = ModelUtil.getClass(sigPackage, "AA");

+        assertTrue(aaType.getKind() == Kind.ANNOTATION);

+        assertSame(aaType, fieldType.getClassDefinition());

+        

+        assertTrue(field.getDefaultValue() instanceof IAnnotation);

+        IAnnotation defaultValue = (IAnnotation)field.getDefaultValue();

+        assertEquals(0, defaultValue.getElements().size());

+        assertSame(aaType, defaultValue.getType().getClassDefinition());

+    }

+

+    @Test

+    public void testAnnotationDefaultsAnnotation2() throws IOException {

+        CompilationUnit src1 = new CompilationUnit("a.A", 

+                "package a; " +

+                "public @interface A {" +

+                "    AA[] aa() default {};" +

+                "}");

+        CompilationUnit src2 = new CompilationUnit("a.AA", 

+                "package a; " +

+                "public @interface AA {}");

+        

+        IApi api = convert(src1, src2);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(sigClass.getKind() == Kind.ANNOTATION);

+        Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField field = annotationFields.iterator().next();

+        assertEquals("aa", field.getName());

+        

+        assertTrue(field.getType() instanceof IArrayType);

+        assertTrue(field.getDefaultValue() instanceof Object[]);

+        assertSame(field.getDefaultValue().getClass(), Object[].class);

+        Object[] defaultValue = (Object[])field.getDefaultValue();

+        assertEquals(0, defaultValue.length);

+    }

+

+    @Test

+    public void testAnnotationDefaultsAnnotation3() throws IOException {

+        CompilationUnit src1 = new CompilationUnit("a.A", 

+                "package a; " +

+                "public @interface A {" +

+                "    AA[] aa() default {@AA,@AA};" +

+                "}");

+        CompilationUnit src2 = new CompilationUnit("a.AA", 

+                "package a; " +

+                "public @interface AA {}");

+        

+        IApi api = convert(src1, src2);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(sigClass.getKind() == Kind.ANNOTATION);

+        Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField field = annotationFields.iterator().next();

+        assertEquals("aa", field.getName());

+        

+        assertTrue(field.getType() instanceof IArrayType);

+        assertTrue(field.getDefaultValue() instanceof Object[]);

+        assertSame(field.getDefaultValue().getClass(), Object[].class);

+        Object[] defaultValue = (Object[])field.getDefaultValue();

+        assertEquals(2, defaultValue.length);

+        

+        IClassDefinition aaType = ModelUtil.getClass(sigPackage, "AA");

+        assertTrue(aaType.getKind() == Kind.ANNOTATION);

+        

+        Object defaultValue0 = defaultValue[0];

+        assertTrue(defaultValue0 instanceof IAnnotation);

+        IAnnotation defaultValue0ann = (IAnnotation)defaultValue0;

+        assertSame(aaType, defaultValue0ann.getType().getClassDefinition());

+        assertEquals(0, defaultValue0ann.getElements().size());

+        

+        Object defaultValue1 = defaultValue[1];

+        assertTrue(defaultValue1 instanceof IAnnotation);

+        IAnnotation defaultValue1ann = (IAnnotation)defaultValue1;

+        assertSame(aaType, defaultValue1ann.getType().getClassDefinition());

+        assertEquals(0, defaultValue1ann.getElements().size());  

+    }

+

+

+

+    @Test

+    public void testAnnotationDefaultsString1() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.A", 

+                "package a;" +

+                "public @interface A {" +

+                "    String str() default \"xxx\";" +

+                "}");

+        IApi api = convert(src);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(sigClass.getKind() == Kind.ANNOTATION);

+        Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField field = annotationFields.iterator().next();

+        assertEquals("str", field.getName());

+        

+        assertTrue(field.getType() instanceof IClassReference);

+        assertEquals("String", ((IClassReference)field.getType()).getClassDefinition().getName());

+        

+        assertTrue(field.getDefaultValue() instanceof String);

+        String defaultValue = (String)field.getDefaultValue();

+        assertEquals("xxx", defaultValue);

+    }

+

+    @Test    

+    public void testAnnotationDefaultsString2() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.A", 

+                "package a;" +

+                "public @interface A {" +

+                "    String[] str() default {};" +

+                "}");

+        IApi api = convert(src);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(sigClass.getKind() == Kind.ANNOTATION);

+        Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField field = annotationFields.iterator().next();

+        assertEquals("str", field.getName());

+        

+        assertTrue(field.getType() instanceof IArrayType);

+        Object defaultValue = field.getDefaultValue();

+        assertTrue(defaultValue instanceof Object[]);

+        assertSame(defaultValue.getClass(), Object[].class);

+        assertEquals(0, ((Object[])defaultValue).length);

+    }

+

+    @Test    

+    public void testAnnotationDefaultsString3() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.A", 

+                "package a;" +

+                "public @interface A {" +

+                "    String[] str() default {\"ONE\", \"TWO\"};" +

+                "}");

+        IApi api = convert(src);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(sigClass.getKind() == Kind.ANNOTATION);

+        Set<IAnnotationField> annotationFields = sigClass.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField field = annotationFields.iterator().next();

+        assertEquals("str", field.getName());

+        

+        assertTrue(field.getType() instanceof IArrayType);

+        assertTrue(field.getDefaultValue() instanceof Object[]);

+        assertSame(field.getDefaultValue().getClass(), Object[].class);

+        Object[] defaultValue = (Object[])field.getDefaultValue();

+        assertEquals(2, defaultValue.length);

+        

+        Object defaultValue0 = defaultValue[0];

+        assertTrue(defaultValue0 instanceof String);

+        String defaultValue0str = (String)defaultValue0;

+        assertEquals("ONE", defaultValue0str);

+

+        Object defaultValue1 = defaultValue[1];

+        assertTrue(defaultValue1 instanceof String);

+        String defaultValue1str = (String)defaultValue1;

+        assertEquals("TWO", defaultValue1str);

+    }

+

+    @Test

+    public void testAnnotationDefaultsClass1() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.A", 

+                "package a;" +

+                "public @interface A {" +

+                "    Class cc() default A.class;" +

+                "}");

+        IApi api = convert(src);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition aType = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(aType.getKind() == Kind.ANNOTATION);

+        Set<IAnnotationField> annotationFields = aType.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField field = annotationFields.iterator().next();

+        assertEquals("cc", field.getName());

+        

+        assertTrue(field.getType() instanceof IClassReference);

+        assertEquals("Class", ((IClassReference)field.getType()).getClassDefinition().getName());

+        Object defaultValue = field.getDefaultValue();

+        assertSame(aType, ((IClassReference)defaultValue).getClassDefinition());

+    }

+

+    @Test

+    public void testAnnotationDefaultsClass2() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.A", 

+                "package a;" +

+                "public @interface A {" +

+                "    Class cc() default void.class;" +

+                "}");

+        IApi api = convert(src);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition aType = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(aType.getKind() == Kind.ANNOTATION);

+        Set<IAnnotationField> annotationFields = aType.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField field = annotationFields.iterator().next();

+        assertEquals("cc", field.getName());

+        

+        assertTrue(field.getType() instanceof IClassReference);

+        assertEquals("Class", ((IClassReference)field.getType()).getClassDefinition().getName());

+        

+        Object defaultValue = field.getDefaultValue();

+        assertTrue(defaultValue instanceof IPrimitiveType);

+        assertEquals("void", ((IPrimitiveType)defaultValue).getName());

+        assertSame(SigPrimitiveType.VOID_TYPE, defaultValue);

+    }

+

+    @Test

+    public void testAnnotationDefaultsClass3() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.A", 

+                "package a;" +

+                "public @interface A {" +

+                "    Class[] cc() default {};" +

+                "}");

+        IApi api = convert(src);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition aType = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(aType.getKind() == Kind.ANNOTATION);

+        Set<IAnnotationField> annotationFields = aType.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField field = annotationFields.iterator().next();

+        assertEquals("cc", field.getName());

+        

+        assertTrue(field.getDefaultValue() instanceof Object[]);

+        assertSame(field.getDefaultValue().getClass(), Object[].class);

+        Object[] defaultValue = (Object[])field.getDefaultValue();

+        assertEquals(0, defaultValue.length);

+    }

+

+    @Test

+    public void testAnnotationDefaultsClass4() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.A", 

+                "package a;" +

+                "public @interface A {" +

+                "    Class[] cc() default {A.class, void.class};" +

+                "}");

+        IApi api = convert(src);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition aType = ModelUtil.getClass(sigPackage, "A");

+        assertTrue(aType.getKind() == Kind.ANNOTATION);

+        Set<IAnnotationField> annotationFields = aType.getAnnotationFields();

+        assertEquals(1, annotationFields.size());

+        IAnnotationField field = annotationFields.iterator().next();

+        assertEquals("cc", field.getName());

+        

+        assertTrue(field.getDefaultValue() instanceof Object[]);

+        assertSame(field.getDefaultValue().getClass(), Object[].class);

+        Object[] defaultValue = (Object[])field.getDefaultValue();

+        assertEquals(2, defaultValue.length);

+        

+        Object defaultValue0 = defaultValue[0];

+        assertTrue(defaultValue0 instanceof ITypeReference);

+        ITypeReference defaultValue0type = (ITypeReference)defaultValue0;

+        assertSame(aType, ((IClassReference)defaultValue0type).getClassDefinition());

+

+        Object defaultValue1 = defaultValue[1];

+        assertTrue(defaultValue1 instanceof ITypeReference);

+        assertTrue(defaultValue1 instanceof IPrimitiveType);

+        IPrimitiveType defaultValue1type = (IPrimitiveType)defaultValue1;

+        assertEquals("void", defaultValue1type.getName());

+        assertSame(SigPrimitiveType.VOID_TYPE, defaultValue1type);

+    }

+    

+    @Test

+    public void testAnnotationRetentionRuntime() throws IOException {

+        CompilationUnit retention = new CompilationUnit("java.lang.annotation.Retention", 

+                "package java.lang.annotation; " +

+                "@Retention(RetentionPolicy.RUNTIME) " + 

+                //"@Target(ElementType.ANNOTATION_TYPE) " + 

+                "public @interface Retention { " +

+                "   RetentionPolicy value() default RetentionPolicy.CLASS; " +

+                "}");

+        CompilationUnit retentionPolicy = new CompilationUnit("java.lang.annotation.RetentionPolicy", 

+                "package java.lang.annotation; " +

+                "public enum RetentionPolicy { " + 

+                "    SOURCE," + 

+                "    CLASS," + 

+                "    RUNTIME" + 

+                "}");

+        CompilationUnit anno = new CompilationUnit("a.A", 

+                "package a;" +

+                "@java.lang.annotation.Retention(value=java.lang.annotation.RetentionPolicy.SOURCE)" +

+                "public @interface A{}");

+        CompilationUnit cla = new CompilationUnit("a.B",  

+                "package a;" +

+                "@A public class B{}");

+        IApi api = convert(anno, cla, retention, retentionPolicy);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition aType = ModelUtil.getClass(sigPackage, "B");

+        assertTrue(aType.getAnnotations().isEmpty());

+    }

+    

+    @Test

+    public void testAnnotationRetentionClass() throws IOException {

+        CompilationUnit retention = new CompilationUnit("java.lang.annotation.Retention", 

+                "package java.lang.annotation; " +

+                "@Retention(RetentionPolicy.RUNTIME) " + 

+                //"@Target(ElementType.ANNOTATION_TYPE) " + 

+                "public @interface Retention { " +

+                "   RetentionPolicy value() default RetentionPolicy.CLASS; " +

+                "}");

+        CompilationUnit retentionPolicy = new CompilationUnit("java.lang.annotation.RetentionPolicy", 

+                "package java.lang.annotation; " +

+                "public enum RetentionPolicy { " + 

+                "    SOURCE," + 

+                "    CLASS," + 

+                "    RUNTIME" + 

+                "}");

+        CompilationUnit anno = new CompilationUnit("a.A", 

+                "package a;" +

+                "@java.lang.annotation.Retention(value=java.lang.annotation.RetentionPolicy.CLASS)" +

+                "public @interface A{}");

+        CompilationUnit cla = new CompilationUnit("a.B",  

+                "package a;" +

+                "@A public class B{}");

+        IApi api = convert(anno, cla, retention, retentionPolicy);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        IClassDefinition aType = ModelUtil.getClass(sigPackage, "B");

+        assertEquals(1, aType.getAnnotations().size());

+    }

+

+}

diff --git a/tools/signature-tools/test/signature/converter/ConvertClassTest.java b/tools/signature-tools/test/signature/converter/ConvertClassTest.java
new file mode 100644
index 0000000..5bcdcb4
--- /dev/null
+++ b/tools/signature-tools/test/signature/converter/ConvertClassTest.java
@@ -0,0 +1,668 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Test;
+
+import signature.converter.util.AbstractConvertTest;
+import signature.converter.util.CompilationUnit;
+import signature.model.IAnnotation;
+import signature.model.IApi;
+import signature.model.IArrayType;
+import signature.model.IClassDefinition;
+import signature.model.IClassReference;
+import signature.model.IConstructor;
+import signature.model.IField;
+import signature.model.IMethod;
+import signature.model.IPackage;
+import signature.model.IParameter;
+import signature.model.IParameterizedType;
+import signature.model.ITypeReference;
+import signature.model.ITypeVariableDefinition;
+import signature.model.ITypeVariableReference;
+import signature.model.Kind;
+import signature.model.Modifier;
+import signature.model.impl.SigPrimitiveType;
+import signature.model.util.ModelUtil;
+
+public abstract class ConvertClassTest extends AbstractConvertTest {
+    
+    @Test
+    public void convertPackageClassTest() throws IOException {
+        IApi api = convert(new CompilationUnit("a.b.A", "package a.b; public class A{}"));
+        IPackage sigPackage = ModelUtil.getPackage(api, "a.b");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals("a.b.A", sigClass.getQualifiedName());
+        assertEquals("A", sigClass.getName());
+        assertEquals("a.b", sigPackage.getName());
+        assertEquals(1, sigPackage.getClasses().size());
+    }
+    
+    @Test
+    public void convertClassClassTest() throws IOException {
+        IApi api = convert(new CompilationUnit("a.A", "package a; public class A{}"));
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals("a.A", sigClass.getQualifiedName());
+        assertEquals("A", sigClass.getName());
+        assertEquals(Kind.CLASS, sigClass.getKind());
+        assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC));
+    }
+    
+    @Test
+    public void convertClassInterfaceTest() throws IOException {
+        IApi api = convert(new CompilationUnit("a.A", "package a; public interface A{}"));
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals("a.A", sigClass.getQualifiedName());
+        assertEquals("A", sigClass.getName());
+        assertEquals(Kind.INTERFACE, sigClass.getKind());
+        assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC));
+    }
+    
+    @Test
+    public void convertClassEnumTest() throws IOException {
+        IApi api = convert(new CompilationUnit("a.A", "package a; public enum A{}"));
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals("a.A", sigClass.getQualifiedName());
+        assertEquals("A", sigClass.getName());
+        assertEquals(Kind.ENUM, sigClass.getKind());
+        assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC));
+    }
+    
+    @Test
+    public void convertClassAnnotationTest() throws IOException {
+        IApi api = convert(new CompilationUnit("a.A", "package a; public @interface A{}"));
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals("a.A", sigClass.getQualifiedName());
+        assertEquals("A", sigClass.getName());
+        assertEquals(Kind.ANNOTATION, sigClass.getKind());
+        assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC));
+    }
+    
+    @Test
+    public void convertAnnotationTest() throws IOException {
+        IApi api = convert(new CompilationUnit("a.A", "package a; @Deprecated public class A{}"));
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals("a.A", sigClass.getQualifiedName());
+        assertEquals("A", sigClass.getName());
+        assertEquals(Kind.CLASS, sigClass.getKind());
+        assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC));
+        assertEquals(1, sigClass.getAnnotations().size());
+        IAnnotation annotation = sigClass.getAnnotations().iterator().next();        
+        assertEquals("java.lang.Deprecated", annotation.getType().getClassDefinition().getQualifiedName());
+    }
+    
+    @Test
+    public void convertAnnotationOnFieldTest() throws IOException {
+        IApi api = convert(new CompilationUnit("a.A", 
+                "package a; " +
+                "public class A{" +
+                "  @Deprecated" +
+                "  public int f;" +
+                "}"));
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals("a.A", sigClass.getQualifiedName());
+        assertEquals("A", sigClass.getName());
+        assertEquals(Kind.CLASS, sigClass.getKind());
+        assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC));
+        assertEquals(1, sigClass.getFields().size());
+        IField field = sigClass.getFields().iterator().next(); 
+        assertEquals("f", field.getName());
+        assertEquals(1, field.getAnnotations().size());
+        IAnnotation annotation = field.getAnnotations().iterator().next();        
+        assertEquals("java.lang.Deprecated", annotation.getType().getClassDefinition().getQualifiedName());
+    }
+    
+    @Test
+    public void convertGenericClass0() throws IOException {
+        IApi api = convert(new CompilationUnit("a.A", "package a; public class A<T> {}"));
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+       assertEquals("a.A", sigClass.getQualifiedName());
+        assertEquals("A", sigClass.getName());
+        assertEquals(Kind.CLASS, sigClass.getKind());
+        assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC));
+        //test type variable
+        assertEquals(1, sigClass.getTypeParameters().size());
+        ITypeVariableDefinition variable = sigClass.getTypeParameters().get(0);
+        assertEquals("T", variable.getName());
+        //test type variable bound 
+        assertEquals(1, variable.getUpperBounds().size());
+        IClassReference bound = (IClassReference) variable.getUpperBounds().get(0);
+        assertEquals("java.lang.Object", bound.getClassDefinition().getQualifiedName());
+    }
+    
+    @Test
+    public void convertGenericClass00() throws IOException {
+        IApi api = convert(new CompilationUnit("a.A", "package a; public class A<T extends Integer> {}"));
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals("a.A", sigClass.getQualifiedName());
+        assertEquals("A", sigClass.getName());
+        assertEquals(Kind.CLASS, sigClass.getKind());
+        assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC));
+        //test type variable
+        assertEquals(1, sigClass.getTypeParameters().size());
+        ITypeVariableDefinition variable = sigClass.getTypeParameters().get(0);
+        assertEquals("T", variable.getName());
+        //test type variable bound 
+        assertEquals(1, variable.getUpperBounds().size());
+        IClassReference bound = (IClassReference) variable.getUpperBounds().get(0);
+        assertEquals("java.lang.Integer", bound.getClassDefinition().getQualifiedName());
+    }
+    
+    @Test
+    public void convertGenericClass1() throws IOException {
+        IApi api = convert(new CompilationUnit("a.A", "package a; public class A<S,T> {}"));
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals("a.A", sigClass.getQualifiedName());
+        assertEquals("A", sigClass.getName());
+        assertEquals(Kind.CLASS, sigClass.getKind());
+        assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC));
+        //test type variable
+        assertEquals(2, sigClass.getTypeParameters().size());
+        ITypeVariableDefinition variableS = sigClass.getTypeParameters().get(0);
+        assertEquals("S", variableS.getName());
+        //test type variable bound 
+        assertEquals(1, variableS.getUpperBounds().size());
+        IClassReference boundS = (IClassReference) variableS.getUpperBounds().get(0);
+        assertEquals("java.lang.Object", boundS.getClassDefinition().getQualifiedName());
+        
+        ITypeVariableDefinition variableT = sigClass.getTypeParameters().get(1);
+        assertEquals("T", variableT.getName());
+        //test type variable bound 
+        assertEquals(1, variableT.getUpperBounds().size());
+        IClassReference boundT = (IClassReference) variableT.getUpperBounds().get(0);
+        assertEquals("java.lang.Object", boundT.getClassDefinition().getQualifiedName());
+    }
+    
+    @Test
+    public void convertGenericClass2() throws IOException {
+        IApi api = convert(new CompilationUnit("a.A", "package a; public class A<S,T extends S> {}"));
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals("a.A", sigClass.getQualifiedName());
+        assertEquals("A", sigClass.getName());
+        assertEquals(Kind.CLASS, sigClass.getKind());
+        assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC));
+        //test type variable
+        assertEquals(2, sigClass.getTypeParameters().size());
+        ITypeVariableDefinition variableS = sigClass.getTypeParameters().get(0);
+        assertEquals("S", variableS.getName());
+        //test type variable bound 
+        assertEquals(1, variableS.getUpperBounds().size());
+        IClassReference boundS = (IClassReference) variableS.getUpperBounds().get(0);
+        assertEquals("java.lang.Object", boundS.getClassDefinition().getQualifiedName());
+        
+        ITypeVariableDefinition variableT = sigClass.getTypeParameters().get(1);
+        assertEquals("T", variableT.getName());
+        //test type variable bound 
+        assertEquals(1, variableT.getUpperBounds().size());
+        ITypeVariableReference boundT = (ITypeVariableReference) variableT.getUpperBounds().get(0);
+        assertSame(variableS, boundT.getTypeVariableDefinition());
+    }
+    
+    @Test
+    public void convertClassImplementsInterface0() throws IOException {
+        IApi api = convert(new CompilationUnit("a.A", "package a; public class A implements Cloneable {}"));
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals("a.A", sigClass.getQualifiedName());
+        assertEquals("A", sigClass.getName());
+        assertEquals(Kind.CLASS, sigClass.getKind());
+        assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC));
+        
+        assertEquals(1, sigClass.getInterfaces().size());
+        IClassDefinition clonable = ((IClassReference) sigClass.getInterfaces().iterator().next()).getClassDefinition();
+        assertEquals("java.lang.Cloneable", clonable.getQualifiedName());
+        assertEquals(Kind.INTERFACE, clonable.getKind());
+    }
+    
+    @Test
+    public void convertClassImplementsInterface1() throws IOException {
+        CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A implements I {}");
+        CompilationUnit interfaceSrc = new CompilationUnit("a.I", "package a; public interface I {}");
+        IApi api = convert(classSrc, interfaceSrc);
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals("a.A", sigClass.getQualifiedName());
+        assertEquals("A", sigClass.getName());
+        assertEquals(Kind.CLASS, sigClass.getKind());
+        assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC));
+        
+        IClassDefinition sigInterface = ModelUtil.getClass(sigPackage, "I");
+        assertEquals("a.I", sigInterface.getQualifiedName());
+        assertEquals("I", sigInterface.getName());
+        assertEquals(Kind.INTERFACE, sigInterface.getKind());
+        assertTrue(sigInterface.getModifiers().contains(Modifier.PUBLIC));
+        
+        assertEquals(1, sigClass.getInterfaces().size());
+        IClassReference interfaze = (IClassReference) sigClass.getInterfaces().iterator().next();
+        assertEquals(Kind.INTERFACE, interfaze.getClassDefinition().getKind());
+        assertSame(sigInterface, interfaze.getClassDefinition());
+    }
+    
+    @Test
+    public void convertClassImplementsGenericInterface0() throws IOException {
+        CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A implements I<String> {}");
+        CompilationUnit interfaceSrc = new CompilationUnit("a.I", "package a; public interface I<T> {}");
+        IApi api = convert(classSrc, interfaceSrc);
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals("a.A", sigClass.getQualifiedName());
+        assertEquals("A", sigClass.getName());
+        assertEquals(Kind.CLASS, sigClass.getKind());
+        assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC));
+        
+        IClassDefinition sigInterface = ModelUtil.getClass(sigPackage, "I");
+        assertEquals("a.I", sigInterface.getQualifiedName());
+        assertEquals("I", sigInterface.getName());
+        assertEquals(Kind.INTERFACE, sigInterface.getKind());
+        assertTrue(sigInterface.getModifiers().contains(Modifier.PUBLIC));
+        
+        assertEquals(1, sigClass.getInterfaces().size());
+        IParameterizedType interfaze = (IParameterizedType) sigClass.getInterfaces().iterator().next();
+        //compare raw type "I"
+        assertSame(sigInterface, interfaze.getRawType().getClassDefinition());
+        //test type argument string
+        assertEquals(1,  interfaze.getTypeArguments().size());
+        IClassReference string = (IClassReference) interfaze.getTypeArguments().get(0);
+        assertEquals("java.lang.String", string.getClassDefinition().getQualifiedName());
+    }
+    
+    @Test
+    public void convertGenericClassImplementsGenericInterface() throws IOException {
+        CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A<T> implements I<T> {}");
+        CompilationUnit interfaceSrc = new CompilationUnit("a.I", "package a; public interface I<T> {}");
+        IApi api = convert(classSrc, interfaceSrc);
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals("a.A", sigClass.getQualifiedName());
+        assertEquals("A", sigClass.getName());
+        assertEquals(Kind.CLASS, sigClass.getKind());
+        assertTrue(sigClass.getModifiers().contains(Modifier.PUBLIC));
+        
+        //get type variable from class
+        assertEquals(1, sigClass.getTypeParameters().size());
+        ITypeVariableDefinition classTypeVar = sigClass.getTypeParameters().get(0);
+        assertEquals("T", classTypeVar.getName());
+        assertSame(sigClass, classTypeVar.getGenericDeclaration());
+        
+        //inspect interface
+        IClassDefinition sigInterface = ModelUtil.getClass(sigPackage, "I");
+        assertEquals("a.I", sigInterface.getQualifiedName());
+        assertEquals("I", sigInterface.getName());
+        assertEquals(Kind.INTERFACE, sigInterface.getKind());
+        assertTrue(sigInterface.getModifiers().contains(Modifier.PUBLIC));
+        
+        //get type variable from interface
+        assertEquals(1, sigInterface.getTypeParameters().size());
+        ITypeVariableDefinition interfaceTypeVar = sigInterface.getTypeParameters().get(0);
+        
+        //get implemented interface from A
+        assertEquals(1, sigClass.getInterfaces().size());
+        IParameterizedType interfaze = (IParameterizedType) sigClass.getInterfaces().iterator().next();
+        
+        //compare raw type "I"
+        assertSame(sigInterface, interfaze.getRawType().getClassDefinition());
+        
+        //test if type variable of A is type argument of I
+        assertEquals(1,  interfaze.getTypeArguments().size());
+        ITypeVariableReference argument = (ITypeVariableReference) interfaze.getTypeArguments().get(0);
+        assertSame(sigClass, argument.getTypeVariableDefinition().getGenericDeclaration());
+        assertEquals(classTypeVar, argument.getTypeVariableDefinition());
+        
+        //test that the two type parameters are not equal
+        assertNotSame(classTypeVar, interfaceTypeVar);
+        assertEquals(classTypeVar.getName(), interfaceTypeVar.getName());
+        assertNotSame(classTypeVar.getGenericDeclaration(), interfaceTypeVar.getGenericDeclaration());
+    }
+    
+    @Test
+    public void convertConstructor0() throws IOException {
+        CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A { public A(){} }");
+        IApi api = convert(classSrc);
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals(1, sigClass.getConstructors().size());
+        IConstructor constructor = sigClass.getConstructors().iterator().next();
+        assertTrue(constructor.getModifiers().contains(Modifier.PUBLIC));
+    }
+    
+    @Test
+    public void convertConstructor1a() throws IOException {
+        CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A { public class B{ } }");
+        IApi api = convert(classSrc);
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A.B");
+        assertEquals(1, sigClass.getConstructors().size());
+        IConstructor constructor = sigClass.getConstructors().iterator().next();
+        assertTrue(constructor.getModifiers().contains(Modifier.PUBLIC));
+    }
+    
+    @Test
+    public void convertConstructor1b() throws IOException {
+        CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A { protected class B{ } }");
+        IApi api = convert(classSrc);
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A.B");
+        assertEquals(1, sigClass.getConstructors().size());
+        IConstructor constructor = sigClass.getConstructors().iterator().next();
+        assertTrue(constructor.getModifiers().contains(Modifier.PROTECTED));
+    }
+    
+    @Test
+    public void convertConstructor2() throws IOException {
+        CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A {}");
+        IApi api = convert(classSrc);
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals(1, sigClass.getConstructors().size());
+    }
+    
+    @Test
+    public void convertConstructor3() throws IOException {
+        CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A { public class B { public B(){}} }");
+        IApi api = convert(classSrc);
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A.B");
+        assertEquals(1, sigClass.getConstructors().size());
+    }
+    
+    @Test
+    public void convertConstructorWithException() throws IOException {
+        CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A { public A() throws NullPointerException{} }");
+        IApi api = convert(classSrc);
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals(1, sigClass.getConstructors().size());
+        IConstructor constructor = sigClass.getConstructors().iterator().next();
+        assertTrue(constructor.getModifiers().contains(Modifier.PUBLIC));
+        assertEquals(1, constructor.getExceptions().size());
+        IClassReference exception = (IClassReference) constructor.getExceptions().iterator().next();
+        assertEquals("java.lang.NullPointerException", exception.getClassDefinition().getQualifiedName());
+    }
+    
+    @Test
+    public void convertConstructorWithParameter() throws IOException {
+        CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A { public A(String param){} }");
+        IApi api = convert(classSrc);
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals(1, sigClass.getConstructors().size());
+        IConstructor constructor = sigClass.getConstructors().iterator().next();
+        assertTrue(constructor.getModifiers().contains(Modifier.PUBLIC));
+        assertEquals(1, constructor.getParameters().size());
+        IParameter param = constructor.getParameters().get(0);
+        assertEquals("java.lang.String", ((IClassReference)param.getType()).getClassDefinition().getQualifiedName());
+    }
+    
+    @Test
+    public void convertConstructorWithGenericParameter() throws IOException {
+        CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A<T> { public A(T param){} }");
+        IApi api = convert(classSrc);
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals(1, sigClass.getConstructors().size());
+        IConstructor constructor = sigClass.getConstructors().iterator().next();
+        assertTrue(constructor.getModifiers().contains(Modifier.PUBLIC));
+        assertEquals(1, constructor.getParameters().size());
+        IParameter param = constructor.getParameters().get(0);
+        ITypeVariableDefinition paramType = ((ITypeVariableReference)param.getType()).getTypeVariableDefinition();
+        assertEquals("T", paramType.getName());
+        assertSame(sigClass, paramType.getGenericDeclaration());
+    }
+    
+    @Test
+    public void convertVoidMethod() throws IOException {
+        CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A { public void m(){} }");
+        IApi api = convert(classSrc);
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals(1, sigClass.getMethods().size());
+        IMethod method = sigClass.getMethods().iterator().next();
+        assertTrue(method.getModifiers().contains(Modifier.PUBLIC));
+        assertEquals("m", method.getName());
+        assertSame(SigPrimitiveType.VOID_TYPE, method.getReturnType());
+    }
+    
+    @Test
+    public void convertArrayMethod() throws IOException {
+        CompilationUnit classSrc = new CompilationUnit("a.A", "package a; public class A { public String[] m(){ return null; } }");
+        IApi api = convert(classSrc);
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        assertEquals(1, sigClass.getMethods().size());
+        IMethod method = sigClass.getMethods().iterator().next();
+        assertTrue(method.getModifiers().contains(Modifier.PUBLIC));
+        assertEquals("m", method.getName());
+        IArrayType arrayType = (IArrayType) method.getReturnType();
+        IClassDefinition clazz = ((IClassReference) arrayType.getComponentType()).getClassDefinition();
+        assertEquals("java.lang.String", clazz.getQualifiedName());
+    }
+    
+     @Test
+    public void testParameterConformance1() throws IOException {
+           IApi api = convert(new CompilationUnit("test.A", 
+                "package test; " +
+                   "import java.util.List;" +
+                   "public class A<T> {" +
+                   "  public String[] a;" +
+                   "  public String[] b;" +
+                   "  public List<String> c;" +
+                   "  public List<String> d;" +
+                   "  public List<T> e;" +
+                   "  public List<T> f;" +
+                   "}"
+           ));
+        IPackage p = ModelUtil.getPackage(api, "test");
+        assertEquals("test", p.getName());
+        IClassDefinition c = ModelUtil.getClass(p, "A");
+        assertEquals("A", c.getName());
+        assertEquals("test.A", c.getQualifiedName());
+        
+        Map<String, IField> fields = new HashMap<String, IField>();
+        for(IField f : c.getFields()){
+            fields.put(f.getName(), f);
+        }
+        assertSame(((IClassReference)((IArrayType)fields.get("a").getType()).getComponentType()).getClassDefinition(), ((IClassReference)((IArrayType)fields.get("b").getType()).getComponentType()).getClassDefinition());
+        assertSame(((IParameterizedType)fields.get("c").getType()).getRawType().getClassDefinition(), ((IParameterizedType)fields.get("d").getType()).getRawType().getClassDefinition());
+        assertSame(((IParameterizedType)fields.get("e").getType()).getRawType().getClassDefinition(), ((IParameterizedType)fields.get("f").getType()).getRawType().getClassDefinition());
+        
+        ITypeReference type = fields.get("f").getType();
+        assertTrue(type instanceof IParameterizedType);
+        ITypeReference typeArgument = ((IParameterizedType)type).getTypeArguments().get(0);
+        ITypeVariableDefinition typeParameter = c.getTypeParameters().get(0);
+        assertSame(((ITypeVariableReference)typeArgument).getTypeVariableDefinition(), typeParameter);
+    }
+
+    @Test
+    public void testParameterConformance2() throws IOException {
+           IApi api = convert(new CompilationUnit("test.A", 
+                "package test; " +
+                   "public class A<T> {" +
+                   "  public <T> T foo(T t){return null;}" +
+                   "}"
+           ));
+        IPackage p = ModelUtil.getPackage(api, "test");
+        assertEquals("test", p.getName());
+
+        IPackage sigPackage = ModelUtil.getPackage(api, "test");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        ITypeVariableDefinition t = sigClass.getTypeParameters().get(0);
+        
+        IMethod sigMethod = sigClass.getMethods().iterator().next();
+        ITypeVariableDefinition t1 = sigMethod.getTypeParameters().get(0);
+        IParameter param = sigMethod.getParameters().get(0);
+        ITypeReference t2 = param.getType();
+        ITypeReference t3 = sigMethod.getReturnType();
+
+        assertSame(t1, ((ITypeVariableReference)t2).getTypeVariableDefinition());
+        assertSame(((ITypeVariableReference)t2).getTypeVariableDefinition(), ((ITypeVariableReference)t3).getTypeVariableDefinition());
+        
+        assertNotSame(t, t1);
+    }
+    
+    @Test
+    public void testInnerReferenceToOuterTypeVariable() throws IOException {
+           IApi api = convert(new CompilationUnit("test.A", 
+                "package test; " +
+                "public class A<T> {" +
+                "  public class B {" +
+                "    public T f;" +
+                "  }  " +
+                "}"
+        ));
+        IPackage p = ModelUtil.getPackage(api, "test");
+        assertEquals("test", p.getName());
+
+        IPackage sigPackage = ModelUtil.getPackage(api, "test");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        ITypeVariableDefinition t = sigClass.getTypeParameters().get(0);
+        
+        IClassDefinition innerClass = ModelUtil.getClass(sigPackage, "A.B");
+        IField field = ModelUtil.getField(innerClass, "f");
+        
+        assertSame(t, ((ITypeVariableReference)field.getType()).getTypeVariableDefinition());
+    }
+    
+    
+    @Test
+    public void convertTypeVariableMultipleUpperBound() throws IOException {
+        String source = 
+            "package a; " +
+            "public class A<T extends Comparable<T> & java.io.Serializable> {}";
+            IApi api = convert(new CompilationUnit("a.A", source));
+            IPackage sigPackage = ModelUtil.getPackage(api, "a");
+            IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+            
+            List<ITypeVariableDefinition> typeParameters = sigClass.getTypeParameters();
+            assertEquals(1, typeParameters.size());
+            
+            ITypeVariableDefinition typeVariable = typeParameters.get(0);
+            List<ITypeReference> upperBounds = typeVariable.getUpperBounds();
+            assertEquals(2, upperBounds.size());
+            ITypeReference firstBound = upperBounds.get(0);
+            ITypeReference secondBound = upperBounds.get(1);
+            
+            assertTrue(firstBound instanceof IParameterizedType);
+            
+            IParameterizedType parametrizedType = (IParameterizedType)firstBound;
+            
+            IClassReference rawType = parametrizedType.getRawType();
+            assertEquals("Comparable", rawType.getClassDefinition().getName());
+            assertEquals(1, parametrizedType.getTypeArguments().size());
+            ITypeVariableReference variable = (ITypeVariableReference) parametrizedType.getTypeArguments().get(0);
+            assertSame(typeVariable, variable.getTypeVariableDefinition());
+            
+            assertTrue(secondBound instanceof IClassReference);
+            IClassReference secondBoundClass = (IClassReference) secondBound;
+            assertEquals("Serializable", secondBoundClass.getClassDefinition().getName());
+    }
+    
+    @Test
+    public void convertPrivateStaticInnerClass0() throws IOException {
+        String source = 
+            "package a; " +
+            "public class A { " +
+            "  private static class I{}" +
+            "  private transient Object i = new I(); " +
+            "}";
+            IApi api = convert(Visibility.PRIVATE, new CompilationUnit("a.A", source));
+            IPackage sigPackage = ModelUtil.getPackage(api, "a");
+            IClassDefinition innerClass = ModelUtil.getClass(sigPackage, "A.I");
+            assertEquals("A.I", innerClass.getName());
+            Set<IConstructor> constructors = innerClass.getConstructors();
+            assertEquals(1, constructors.size());
+    }
+    
+    @Test
+    public void convertPrivateStaticInnerClass1() throws IOException {
+        String source = 
+            "package a; " +
+            "public class A {" + 
+            "  private static class B {" + 
+            "    public static class C {}" + 
+            "  }" + 
+            "}";
+            IApi api = convert(new CompilationUnit("a.A", source));
+            IPackage sigPackage = ModelUtil.getPackage(api, "a");
+            assertEquals(1, sigPackage.getClasses().size());
+    }
+    
+    /**
+     * Tests whether the first constructor argument is removed.
+     */
+    @Test
+    public void convertNonStaticInnerClassConstructor0() throws IOException {
+        String source = 
+            "package a; " +
+            "public class A {" + 
+            "  public class B {" + 
+            "      public B(){}" +
+            "  }" + 
+            "}";
+            IApi api = convert(new CompilationUnit("a.A", source));
+            IPackage sigPackage = ModelUtil.getPackage(api, "a");
+            IClassDefinition innerClass = ModelUtil.getClass(sigPackage, "A.B");
+            assertEquals(1, innerClass.getConstructors().size());
+            Set<IConstructor> constructors = innerClass.getConstructors();
+            IConstructor first = constructors.iterator().next();
+            //implicit A.this reference must be removed
+            assertEquals(0, first.getParameters().size());
+    }
+    
+    /**
+     * Tests whether the first constructor argument is removed.
+     */
+    @Test
+    public void convertNonStaticInnerClassConstructor1() throws IOException {
+        String source = 
+            "package a; " +
+            "public class A {" + 
+            "  public class B {}" + 
+            "}";
+            IApi api = convert(new CompilationUnit("a.A", source));
+            IPackage sigPackage = ModelUtil.getPackage(api, "a");
+            IClassDefinition innerClass = ModelUtil.getClass(sigPackage, "A.B");
+            assertEquals(1, innerClass.getConstructors().size());
+            Set<IConstructor> constructors = innerClass.getConstructors();
+            IConstructor first = constructors.iterator().next();
+            //implicit A.this reference must be removed
+            assertEquals(0, first.getParameters().size());
+    }
+    
+    
+   
+}
diff --git a/tools/signature-tools/test/signature/converter/ConvertEnumTest.java b/tools/signature-tools/test/signature/converter/ConvertEnumTest.java
new file mode 100644
index 0000000..98ebd61
--- /dev/null
+++ b/tools/signature-tools/test/signature/converter/ConvertEnumTest.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Test;
+
+import signature.converter.util.AbstractConvertTest;
+import signature.converter.util.CompilationUnit;
+import signature.model.IApi;
+import signature.model.IArrayType;
+import signature.model.IClassDefinition;
+import signature.model.IClassReference;
+import signature.model.IConstructor;
+import signature.model.IEnumConstant;
+import signature.model.IField;
+import signature.model.IMethod;
+import signature.model.IPackage;
+import signature.model.IParameter;
+import signature.model.Kind;
+import signature.model.Modifier;
+import signature.model.util.ModelUtil;
+
+public abstract class ConvertEnumTest extends AbstractConvertTest {
+    
+    @Test
+    public void testEnum1() throws IOException {
+        IApi api = convert(new CompilationUnit("test.A", 
+                "package test; " +
+                "public enum A {" +
+                "  ONE, TWO, THREE" +
+                "}"));
+        IPackage sigPackage = ModelUtil.getPackage(api, "test");
+        IClassDefinition c = ModelUtil.getClass(sigPackage, "A");
+        assertNotNull(c);
+        assertTrue(c.getKind() == Kind.ENUM);
+
+        Set<IEnumConstant> constants = c.getEnumConstants();
+        assertEquals(3, constants.size());
+        
+        Set<String> constantNames = new HashSet<String>();
+        for (IEnumConstant constant : constants) {
+            constantNames.add(constant.getName());
+        }
+        
+        assertTrue(constantNames.contains("ONE"));
+        assertTrue(constantNames.contains("TWO"));
+        assertTrue(constantNames.contains("THREE"));
+        
+//        IEnumConstant[] enumConstants = new IEnumConstant[3];
+//        for (IEnumConstant enumConstant : constants) {
+//            enumConstants[enumConstant.getOrdinal()] = enumConstant;
+//            assertEquals(0, enumConstant.getAnnotations().size());
+//            assertSame(c, enumConstant.getType());
+//        }
+//        
+//        assertEquals("ONE", enumConstants[0].getName());
+//        assertEquals("TWO", enumConstants[1].getName());
+//        assertEquals("THREE", enumConstants[2].getName());
+    }
+
+    @Test
+    public void testEnum2() throws IOException {
+        IApi api = convert(new CompilationUnit("test.A", 
+                "package test; " +
+                "public enum A {" +
+                "  ONE, TWO, THREE;" +
+                "  public static A FOUR = ONE;" +
+                "}"));
+        IPackage sigPackage = ModelUtil.getPackage(api, "test");
+        IClassDefinition c = ModelUtil.getClass(sigPackage, "A");
+        assertNotNull(c);
+        assertTrue(c.getKind() == Kind.ENUM);
+
+        Set<IEnumConstant> constants = c.getEnumConstants();
+        assertEquals(3, constants.size());
+        
+        Set<IField> fields = c.getFields();
+        assertEquals(1, fields.size());
+        IField field = c.getFields().iterator().next();
+        
+        assertEquals("FOUR", field.getName());
+        assertSame(c, ((IClassReference)field.getType()).getClassDefinition());
+    }
+
+
+   @Test
+    public void testEnum3() throws IOException {
+        IApi api = convert(new CompilationUnit("test.A", 
+                "package test; " +
+                "public enum A {" +
+                "  ONE(1), TWO(2), THREE(3);" +
+                "  A(int value){}" +
+                "}"));
+        IPackage sigPackage = ModelUtil.getPackage(api, "test");
+        IClassDefinition c = ModelUtil.getClass(sigPackage, "A");
+        assertNotNull(c);
+        assertTrue(c.getKind() == Kind.ENUM);
+
+        Set<IEnumConstant> constants = c.getEnumConstants();
+        assertEquals(3, constants.size());
+        
+        Set<IConstructor> ctors = c.getConstructors();
+        assertEquals(0, ctors.size());
+
+        Set<IMethod> methods = c.getMethods();
+        assertEquals(2, methods.size());
+        Map<String, IMethod> map = new HashMap<String, IMethod>();
+        for(IMethod m : methods){
+            map.put(m.getName(), m);
+        }
+        
+        IMethod values = map.get("values");
+        assertNotNull(values);
+        assertEquals(0, values.getParameters().size());
+        assertTrue(values.getReturnType() instanceof IArrayType);
+        assertSame(c, ((IClassReference)((IArrayType)values.getReturnType()).getComponentType()).getClassDefinition());
+        assertTrue(c.getModifiers().contains(Modifier.PUBLIC));
+        assertFalse(c.getModifiers().contains(Modifier.STATIC));
+        assertTrue(c.getModifiers().contains(Modifier.FINAL));
+        
+        IMethod valueOf = map.get("valueOf");
+        assertNotNull(valueOf);
+        assertEquals(1, valueOf.getParameters().size());
+        IParameter param = valueOf.getParameters().iterator().next();
+        assertEquals("java.lang.String", ((IClassReference)param.getType()).getClassDefinition().getQualifiedName());
+        assertSame(c, ((IClassReference)valueOf.getReturnType()).getClassDefinition());
+    }
+   
+   @Test
+   public void testEnum4() throws IOException {
+       IApi api = convert(new CompilationUnit("test.A", 
+               "package test; " +
+               "public enum A {" +
+               "  ONE { void m(){} }, TWO{ void m(){} };" +
+               "  abstract void m();" +
+               "}"));
+       IPackage sigPackage = ModelUtil.getPackage(api, "test");
+       IClassDefinition c = ModelUtil.getClass(sigPackage, "A");
+       assertNotNull(c);
+       assertTrue(c.getKind() == Kind.ENUM);
+
+       Set<IEnumConstant> constants = c.getEnumConstants();
+       assertEquals(2, constants.size());
+       
+       Set<IConstructor> ctors = c.getConstructors();
+       assertEquals(0, ctors.size());
+
+       Set<IMethod> methods = c.getMethods();
+       assertEquals(2, methods.size());
+       Map<String, IMethod> map = new HashMap<String, IMethod>();
+       for(IMethod m : methods){
+           map.put(m.getName(), m);
+       }
+       
+       IMethod values = map.get("values");
+       assertNotNull(values);
+       assertEquals(0, values.getParameters().size());
+       assertTrue(values.getReturnType() instanceof IArrayType);
+       assertSame(c, ((IClassReference)((IArrayType)values.getReturnType()).getComponentType()).getClassDefinition());
+       assertTrue(c.getModifiers().contains(Modifier.PUBLIC));
+       assertFalse(c.getModifiers().contains(Modifier.STATIC));
+       assertFalse(c.getModifiers().contains(Modifier.FINAL));
+   }
+
+}
diff --git a/tools/signature-tools/test/signature/converter/ConvertPackageTest.java b/tools/signature-tools/test/signature/converter/ConvertPackageTest.java
new file mode 100644
index 0000000..edd2a41
--- /dev/null
+++ b/tools/signature-tools/test/signature/converter/ConvertPackageTest.java
@@ -0,0 +1,69 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * 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 signature.converter;

+

+import static org.junit.Assert.assertEquals;

+

+import java.io.IOException;

+

+import org.junit.Test;

+

+import signature.converter.util.AbstractConvertTest;

+import signature.converter.util.CompilationUnit;

+import signature.model.IAnnotation;

+import signature.model.IApi;

+import signature.model.IPackage;

+import signature.model.util.ModelUtil;

+

+public abstract class ConvertPackageTest extends AbstractConvertTest {

+

+    // tests whether package annotations are returned

+    @Test

+    public void testPackageAnnotation() throws IOException {

+        CompilationUnit packageSrc = new CompilationUnit("a.package-info", "@Deprecated package a;");

+        CompilationUnit classSrc = new CompilationUnit("a.X", "package a; public class X{}");

+        IApi api = convert(classSrc, packageSrc);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        assertEquals(1, sigPackage.getAnnotations().size());

+        IAnnotation annotation = sigPackage.getAnnotations().iterator().next();        

+        assertEquals("java.lang.Deprecated", annotation.getType().getClassDefinition().getQualifiedName());

+    }

+        

+    // tests that package-info is not returned as class 

+    @Test

+    public void testNumberOfClasses1() throws IOException {

+        CompilationUnit packageSrc = new CompilationUnit("a.package-info", "@Deprecated package a;");

+        CompilationUnit classSrc = new CompilationUnit("a.X", "package a; public class X{}");

+        IApi api = convert(classSrc, packageSrc);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        assertEquals(1, sigPackage.getClasses().size());

+    }

+        

+    // tests that nested classes are returned as package classes 

+    @Test

+    public void testNumberOfClasses2() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.X",

+                "package a;" +

+                "public class X{" +

+                "   public static class Y{}" +

+                "}");

+        IApi api = convert(src);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        assertEquals(2, sigPackage.getClasses().size());

+    }

+        

+}
\ No newline at end of file
diff --git a/tools/signature-tools/test/signature/converter/ConvertParameterizedTypeTest.java b/tools/signature-tools/test/signature/converter/ConvertParameterizedTypeTest.java
new file mode 100644
index 0000000..653d42f
--- /dev/null
+++ b/tools/signature-tools/test/signature/converter/ConvertParameterizedTypeTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import org.junit.Test;
+
+import signature.converter.util.AbstractConvertTest;
+import signature.converter.util.CompilationUnit;
+import signature.model.IApi;
+import signature.model.IClassDefinition;
+import signature.model.IField;
+import signature.model.IPackage;
+import signature.model.IParameterizedType;
+import signature.model.ITypeReference;
+import signature.model.util.ModelUtil;
+
+public abstract class ConvertParameterizedTypeTest extends AbstractConvertTest {
+    /**
+     * [L, a, /, A, $, B, <, L, j, a, v, a, /, l, a, n, g, /, I, n, t, e, g, e, r, ;, >, ;]
+     * '$' - separated
+     * @throws IOException
+     */
+    @Test
+    public void convertParameterizedType() throws IOException {
+        String source = 
+        "package a; " +
+        "public class A{" +
+        "  public class B<T> {} " +
+        "  public A.B<Integer> f; "+
+        "}";
+        IApi api = convert(new CompilationUnit("a.A", source));
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        IField field = ModelUtil.getField(sigClass, "f");
+        
+        ITypeReference type = field.getType();
+        assertTrue(type instanceof IParameterizedType);
+        
+        IParameterizedType parametrizedType = (IParameterizedType)type;
+        ITypeReference ownerType = parametrizedType.getOwnerType();
+        assertNotNull(ownerType);
+    }
+    
+    @Test
+    public void convertWildcardLowerBound() throws IOException {
+        String clazz = 
+        "package a; " +
+        "public final class A<T> implements I<T>{ " +
+        " abstract class Super{} " +
+        " final class Sub extends Super implements I<T>{} " +
+        "}";
+        String interfaze = 
+            "package a; " +
+            "public interface I <T>{}";
+        IApi api = convert(Visibility.PRIVATE, new CompilationUnit("a.A", clazz),new CompilationUnit("a.I", interfaze));
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A.Sub");
+        System.out.println(sigClass);
+    }
+    
+    public class A{
+      public class B<T> {}
+      public A.B<Integer> f;
+    }
+   
+    @Test
+    public void reflectionTest0() throws SecurityException, NoSuchFieldException{
+        Field field = A.class.getDeclaredField("f");
+        ParameterizedType paramType = (ParameterizedType)field.getGenericType();
+        assertNotNull(paramType.getOwnerType());
+    }
+    
+    public static class C<T>{}
+    
+    ConvertParameterizedTypeTest.C<String> f;
+     
+      @Test
+      public void reflectionTest1() throws SecurityException, NoSuchFieldException{
+          Field field = ConvertParameterizedTypeTest.class.getDeclaredField("f");
+          ParameterizedType paramType = (ParameterizedType)field.getGenericType();
+          assertNotNull(paramType.getOwnerType());
+      }
+      
+      public static class E<T>{
+          static class F<Q>{}
+          E.F<String> f;
+      }
+      
+       
+     @Test
+    public void reflectionTest2() throws SecurityException, NoSuchFieldException {
+        Field field = E.class.getDeclaredField("f");
+        ParameterizedType paramType = (ParameterizedType) field.getGenericType();
+        assertNotNull(paramType.getOwnerType());
+    }
+}
diff --git a/tools/signature-tools/test/signature/converter/ConvertVisibilityTest.java b/tools/signature-tools/test/signature/converter/ConvertVisibilityTest.java
new file mode 100644
index 0000000..09fc32f
--- /dev/null
+++ b/tools/signature-tools/test/signature/converter/ConvertVisibilityTest.java
@@ -0,0 +1,173 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * 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 signature.converter;

+

+import static org.junit.Assert.assertEquals;

+import static org.junit.Assert.assertNotNull;

+

+import java.io.IOException;

+import java.util.Set;

+

+import org.junit.Test;

+

+import signature.converter.Visibility;

+import signature.converter.util.AbstractConvertTest;

+import signature.converter.util.CompilationUnit;

+import signature.model.IApi;

+import signature.model.IClassDefinition;

+import signature.model.IMethod;

+import signature.model.IPackage;

+import signature.model.util.ModelUtil;

+

+public abstract class ConvertVisibilityTest extends AbstractConvertTest {

+

+    @Test

+    public void testVisibilityMethods1() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.A", 

+                "package a;" +

+                "public class A{" +

+                "   public void foo1(){}" +

+                "   protected void foo2(){}" +

+                "   void foo3(){}" +

+                "   private void foo4(){}" +

+                "}");

+

+        IApi api = convert(Visibility.PUBLIC, src);

+        IPackage p = ModelUtil.getPackage(api, "a");

+        IClassDefinition c = ModelUtil.getClass(p, "A");

+        Set<IMethod> methods = c.getMethods();

+        assertEquals(1, methods.size());

+    }

+    

+    @Test

+    public void testVisibilityMethods2() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.A", 

+                "package a;" +

+                "public class A{" +

+                "   public void foo1(){}" +

+                "   protected void foo2(){}" +

+                "   void foo3(){}" +

+                "   private void foo4(){}" +

+                "}");

+

+        IApi api = convert(Visibility.PROTECTED, src);

+        IPackage p = ModelUtil.getPackage(api, "a");

+        IClassDefinition c = ModelUtil.getClass(p, "A");

+        Set<IMethod> methods = c.getMethods();

+        assertEquals(2, methods.size());

+    }

+    

+    @Test

+    public void testVisibilityMethods3() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.A", 

+                "package a;" +

+                "public class A{" +

+                "   public void foo1(){}" +

+                "   protected void foo2(){}" +

+                "   void foo3(){}" +

+                "   private void foo4(){}" +

+                "}");

+

+        IApi api = convert(Visibility.PACKAGE, src);

+        IPackage p = ModelUtil.getPackage(api, "a");

+        IClassDefinition c = ModelUtil.getClass(p, "A");

+        Set<IMethod> methods = c.getMethods();

+        assertEquals(3, methods.size());

+    }

+    

+    @Test

+    public void testVisibilityMethods4() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.A", 

+                "package a;" +

+                "public class A{" +

+                "   public void foo1(){}" +

+                "   protected void foo2(){}" +

+                "   void foo3(){}" +

+                "   private void foo4(){}" +

+                "}");

+

+        IApi api = convert(Visibility.PRIVATE, src);

+        IPackage p = ModelUtil.getPackage(api, "a");

+        IClassDefinition c = ModelUtil.getClass(p, "A");

+        Set<IMethod> methods = c.getMethods();

+        assertEquals(4, methods.size());

+    }

+    

+    @Test

+    public void testVisibility1() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.X1", 

+                "package a;" +

+                "public class X1{" +

+                "   static class X2{}" +

+                "   protected static class X3{}" +

+                "   private static class X4{}" +

+                "}");

+

+        IApi api = convert(Visibility.PUBLIC, src);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        assertEquals(1, sigPackage.getClasses().size());

+    }

+

+    @Test

+    public void testVisibility2() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.X1", 

+                "package a;" +

+                "public class X1{" +

+                "   static class X2{}" +

+                "   protected static class X3{}" +

+                "   private static class X4{}" +

+                "}");

+

+        IApi api = convert(Visibility.PROTECTED, src);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        assertEquals(2, sigPackage.getClasses().size());

+        assertNotNull(ModelUtil.getClass(sigPackage, "X1.X3"));

+    }

+

+    @Test

+    public void testVisibility3() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.X1", 

+                "package a;" +

+                "public class X1{" +

+                "   static class X2{}" +

+                "   protected static class X3{}" +

+                "   private static class X4{}" +

+                "}");

+

+        IApi api = convert(Visibility.PACKAGE, src);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        assertEquals(3, sigPackage.getClasses().size());

+        assertNotNull(ModelUtil.getClass(sigPackage, "X1.X2"));

+    }

+    

+    @Test

+    public void testVisibility4() throws IOException {

+        CompilationUnit src = new CompilationUnit("a.X1", 

+                "package a;" +

+                "public class X1{" +

+                "   static class X2{}" +

+                "   protected static class X3{}" +

+                "   private static class X4{}" +

+                "}");

+

+        IApi api = convert(Visibility.PRIVATE, src);

+        IPackage sigPackage = ModelUtil.getPackage(api, "a");

+        assertEquals(4, sigPackage.getClasses().size());

+        assertNotNull(ModelUtil.getClass(sigPackage, "X1.X4"));

+    }

+

+}
\ No newline at end of file
diff --git a/tools/signature-tools/test/signature/converter/ConvertWildcardTest.java b/tools/signature-tools/test/signature/converter/ConvertWildcardTest.java
new file mode 100644
index 0000000..d18c568
--- /dev/null
+++ b/tools/signature-tools/test/signature/converter/ConvertWildcardTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import signature.converter.util.AbstractConvertTest;
+import signature.converter.util.CompilationUnit;
+import signature.model.IApi;
+import signature.model.IClassDefinition;
+import signature.model.IClassReference;
+import signature.model.IField;
+import signature.model.IPackage;
+import signature.model.IParameterizedType;
+import signature.model.ITypeReference;
+import signature.model.IWildcardType;
+import signature.model.util.ModelUtil;
+
+import java.io.IOException;
+
+public abstract class ConvertWildcardTest extends AbstractConvertTest {
+    
+    @Test
+    public void convertWildcardUpperBound() throws IOException {
+        String source = 
+            "package a; " +
+            "public class A{" +
+            "  public java.util.Set<? extends Number> f; "+
+            "}";
+            IApi api = convert(new CompilationUnit("a.A", source));
+            IPackage sigPackage = ModelUtil.getPackage(api, "a");
+            IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+            IField field = ModelUtil.getField(sigClass, "f");
+            
+            ITypeReference type = field.getType();
+            assertTrue(type instanceof IParameterizedType);
+            
+            IParameterizedType parametrizedType = (IParameterizedType)type;
+            
+            IClassDefinition rawType = parametrizedType.getRawType().getClassDefinition();
+            assertEquals("Set", rawType.getName());
+            
+            assertEquals(1, parametrizedType.getTypeArguments().size());
+            IWildcardType wildcardType = (IWildcardType) parametrizedType.getTypeArguments().get(0);
+            assertEquals(1, wildcardType.getUpperBounds().size());
+            ITypeReference upperBound = wildcardType.getUpperBounds().get(0);
+            assertTrue(upperBound instanceof IClassReference);
+            
+            assertEquals("Number", ((IClassReference)upperBound).getClassDefinition().getName());
+    }    
+    
+    @Test
+    public void convertWildcardLowerBound() throws IOException {
+        String source = 
+        "package a; " +
+        "public class A{" +
+        "  public java.util.Set<? super Number> f; "+
+        "}";
+        IApi api = convert(new CompilationUnit("a.A", source));
+        IPackage sigPackage = ModelUtil.getPackage(api, "a");
+        IClassDefinition sigClass = ModelUtil.getClass(sigPackage, "A");
+        IField field = ModelUtil.getField(sigClass, "f");
+        
+        ITypeReference type = field.getType();
+        assertTrue(type instanceof IParameterizedType);
+        
+        IParameterizedType parametrizedType = (IParameterizedType)type;
+        
+        IClassDefinition rawType = parametrizedType.getRawType().getClassDefinition();
+        assertEquals("Set", rawType.getName());
+        
+        assertEquals(1, parametrizedType.getTypeArguments().size());
+        IWildcardType wildcardType = (IWildcardType) parametrizedType.getTypeArguments().get(0);
+        assertEquals(1, wildcardType.getUpperBounds().size());
+        ITypeReference upperBound = wildcardType.getUpperBounds().get(0);
+        assertTrue(upperBound instanceof IClassReference);
+        assertEquals("Object", ((IClassReference)upperBound).getClassDefinition().getName());
+        
+        ITypeReference lowerBound = wildcardType.getLowerBound();
+        assertTrue(lowerBound instanceof IClassReference);
+        assertEquals("Number", ((IClassReference)lowerBound).getClassDefinition().getName());
+    }
+}
diff --git a/tools/signature-tools/test/signature/converter/dex/DexExternalizerTest.java b/tools/signature-tools/test/signature/converter/dex/DexExternalizerTest.java
new file mode 100644
index 0000000..8e27da5
--- /dev/null
+++ b/tools/signature-tools/test/signature/converter/dex/DexExternalizerTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter.dex;
+
+import org.junit.Test;
+
+import signature.converter.Visibility;
+import signature.io.IApiExternalizer;
+import signature.io.impl.BinaryApi;
+import signature.model.IApi;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+
+public class DexExternalizerTest {
+    
+    @Test
+    public void testExternalizer() throws IOException{
+        DexToSigConverter converter = new DexToSigConverter();
+        IApi api = converter.convertApi("Dex Tests", DexUtil.getDexFiles(new HashSet<String>(Arrays.asList(new String[]{"resources/javaCore.dex"}))), Visibility.PRIVATE);
+        System.setProperty("sun.io.serialization.extendedDebugInfo", "true");
+        IApiExternalizer externalizer = new BinaryApi();
+        externalizer.externalizeApi("dex-spec", api);
+    }
+}
diff --git a/tools/signature-tools/test/signature/converter/dex/DexTestConverter.java b/tools/signature-tools/test/signature/converter/dex/DexTestConverter.java
new file mode 100644
index 0000000..b6b90fa
--- /dev/null
+++ b/tools/signature-tools/test/signature/converter/dex/DexTestConverter.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter.dex;
+
+import dex.reader.util.JavaSource;
+import dex.reader.util.JavaSourceToDexUtil;
+import dex.structure.DexFile;
+import signature.converter.Visibility;
+import signature.converter.dex.DexToSigConverter;
+import signature.converter.util.AbstractTestSourceConverter;
+import signature.converter.util.CompilationUnit;
+import signature.model.IApi;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+public class DexTestConverter extends AbstractTestSourceConverter {
+
+    public IApi convert(Visibility visibility, Set<CompilationUnit> units) throws IOException {
+        JavaSourceToDexUtil toDexUtil = new JavaSourceToDexUtil();
+        DexToSigConverter converter = new DexToSigConverter();
+        Set<JavaSource> sources = new HashSet<JavaSource>();
+        for (CompilationUnit unit : units) {
+            sources.add(new JavaSource(unit.getName(), unit.getSource()));
+        }
+        DexFile dexFile = toDexUtil.getAllFrom(sources);
+        return converter.convertApi("Dex Tests", Collections.singleton(dexFile), visibility);
+    }
+
+}
diff --git a/tools/signature-tools/test/signature/converter/dex/DexUtilTest.java b/tools/signature-tools/test/signature/converter/dex/DexUtilTest.java
new file mode 100644
index 0000000..ff005fb
--- /dev/null
+++ b/tools/signature-tools/test/signature/converter/dex/DexUtilTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter.dex;
+
+
+import dex.reader.DexTestsCommon;
+import dex.reader.util.JavaSource;
+import dex.reader.util.JavaSourceToDexUtil;
+import dex.structure.DexClass;
+import dex.structure.DexFile;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import signature.converter.dex.DexToSigConverter;
+import signature.model.impl.SigPackage;
+import static signature.converter.dex.DexUtil.*;
+
+import java.io.IOException;
+
+import static org.junit.Assert.*;
+
+public class DexUtilTest extends DexTestsCommon {
+
+    private JavaSourceToDexUtil dexUtil;
+    private DexToSigConverter converter;
+    
+    @Before
+    public void setupDexUtil(){
+        dexUtil = new JavaSourceToDexUtil();
+        converter = new DexToSigConverter();
+    }
+    
+    @Test
+    public void convertPackageTest(){
+        SigPackage aPackage = converter.convertPackage("a");
+        assertEquals("a", aPackage.getName());
+        
+        aPackage = converter.convertPackage("a.b.c");
+        assertEquals("a.b.c", aPackage.getName());
+    }
+    
+    @Test
+    public void getPackageNameTest(){
+        assertEquals("",getPackageName("LA;"));
+        assertEquals("a",getPackageName("La/A;"));
+        assertEquals("a.b.c",getPackageName("La/b/c/A;"));
+    }
+    
+    @Test
+    public void getClassNameTest(){
+        assertEquals("A",getClassName("LA;"));
+        assertEquals("A",getClassName("La/A;"));
+        assertEquals("A",getClassName("La/b/c/A;"));
+    }
+    
+    @Test
+    public void hasGenericSignatureTest() throws IOException {
+        DexFile dexFile = dexUtil.getFrom(new JavaSource("A", "public class A{}"));
+        DexClass dexClass = getClass(dexFile, "LA;");
+        assertFalse(hasGenericSignature(dexClass));
+
+        dexFile = dexUtil.getFrom(new JavaSource("B", "public class B<T>{}"));
+        dexClass = getClass(dexFile, "LB;");
+        assertTrue(hasGenericSignature(dexClass));
+    }
+    
+    @Test
+    public void getGenericSignatureTest() throws IOException {
+        DexFile dexFile =  dexUtil.getFrom(new JavaSource("A", "public class A{}"));
+        DexClass dexClass = getClass(dexFile, "LA;");
+        assertNull(getGenericSignature(dexClass));
+        
+        dexFile =  dexUtil.getFrom(new JavaSource("B", "public class B<T>{}"));
+        dexClass = getClass(dexFile, "LB;");
+        assertEquals("<T:Ljava/lang/Object;>Ljava/lang/Object;", getGenericSignature(dexClass));
+    }
+    
+    
+    
+}
diff --git a/tools/signature-tools/test/signature/converter/dex/GenericSignatureParserTest.java b/tools/signature-tools/test/signature/converter/dex/GenericSignatureParserTest.java
new file mode 100644
index 0000000..52d73f8
--- /dev/null
+++ b/tools/signature-tools/test/signature/converter/dex/GenericSignatureParserTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter.dex;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import dex.reader.DexTestsCommon;
+import dex.reader.util.JavaSource;
+import dex.reader.util.JavaSourceToDexUtil;
+import dex.structure.DexClass;
+import dex.structure.DexFile;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import signature.converter.dex.DexToSigConverter;
+import signature.converter.dex.DexUtil;
+import signature.converter.dex.GenericSignatureParser;
+import signature.model.impl.SigClassDefinition;
+import signature.model.util.TypePool;
+
+import java.io.IOException;
+
+public class GenericSignatureParserTest extends DexTestsCommon{
+    
+    private DexToSigConverter converter;
+    private JavaSourceToDexUtil dexUtil;
+    private GenericSignatureParser parser;
+
+    @Before
+    public void setupConverter(){
+        converter = new DexToSigConverter();
+        dexUtil = new JavaSourceToDexUtil();
+        parser = new GenericSignatureParser(new TypePool(), converter);
+    }
+    
+    @Test
+    public void getGenericSignatureTest() throws IOException {
+        DexFile  dexFile =  dexUtil.getFrom(new JavaSource("B", "public class B<T>{}"));
+        DexClass dexClass = getClass(dexFile, "LB;");
+        assertEquals("<T:Ljava/lang/Object;>Ljava/lang/Object;", DexUtil.getGenericSignature(dexClass));
+        SigClassDefinition sigClass = converter.convertClass(dexClass);
+        
+        parser.parseForClass(sigClass, DexUtil.getGenericSignature(dexClass));
+        //type parameter name
+        assertEquals(1, parser.formalTypeParameters.size());
+        assertEquals("T", parser.formalTypeParameters.get(0).getName());
+        //type parameter declaration
+        assertSame(sigClass, parser.formalTypeParameters.get(0).getGenericDeclaration());
+        //type parameter upper bounds
+        assertEquals(1, parser.formalTypeParameters.get(0).getUpperBounds().size());
+//        IType type = parser.formalTypeParameters.get(0).getUpperBounds().get(0);
+        
+    }
+}
diff --git a/tools/signature-tools/test/signature/converter/doclet/DocletTestConverter.java b/tools/signature-tools/test/signature/converter/doclet/DocletTestConverter.java
new file mode 100644
index 0000000..8e867dd
--- /dev/null
+++ b/tools/signature-tools/test/signature/converter/doclet/DocletTestConverter.java
@@ -0,0 +1,182 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * 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 signature.converter.doclet;

+

+import java.io.File;

+import java.io.FileWriter;

+import java.io.IOException;

+import java.io.PrintWriter;

+import java.io.StringWriter;

+import java.lang.reflect.Constructor;

+import java.util.HashSet;

+import java.util.Set;

+

+import signature.converter.Visibility;

+import signature.converter.doclet.DocletToSigConverter;

+import signature.converter.util.CompilationUnit;

+import signature.model.IApi;

+import signature.model.util.ModelUtil;

+

+import com.sun.javadoc.RootDoc;

+import com.sun.tools.javac.util.Context;

+import com.sun.tools.javac.util.ListBuffer;

+import com.sun.tools.javac.util.Options;

+import com.sun.tools.javadoc.JavadocTool;

+import com.sun.tools.javadoc.Messager;

+import com.sun.tools.javadoc.ModifierFilter;

+import com.sun.tools.javadoc.RootDocImpl;

+

+public class DocletTestConverter extends signature.converter.util.AbstractTestSourceConverter {

+

+    static String sourcepath;

+    static String separator;

+    

+    static {

+        separator = System.getProperty("file.separator");

+

+        sourcepath = System.getProperty("java.io.tmpdir");

+        sourcepath = sourcepath + separator + "cts" + separator;

+        System.out.println(">> "+sourcepath);

+    }

+

+    public IApi convert(Visibility visibility, Set<CompilationUnit> units) throws IOException {

+        try {

+            Set<String> packages = new HashSet<String>();

+            for(CompilationUnit u : units){

+                putSource(u);

+                String p = ModelUtil.getPackageName(u.getName());

+                assert p.length() > 0 : "default package not supported by doclets";

+                packages.add(p);

+            }

+            

+            RootDoc root = getRootDoc(visibility, packages);

+

+            DocletToSigConverter converter = new DocletToSigConverter();

+            

+            IApi api = converter.convertDocletRoot("Doclet Test", root, visibility, packages);

+            return api;

+        }

+        finally {

+            removeSources();

+        }

+    }

+    

+    public static void putSource(CompilationUnit source) throws IOException {

+        String directory = sourcepath;

+        String filename = source.getName();    // a.b.C

+        int pos = filename.indexOf(".");

+        while(pos > 0) {

+            directory = directory + filename.substring(0, pos) + separator;

+            filename = filename.substring(pos+1);

+            pos = filename.indexOf(".");

+        }

+        

+        File file = new File(directory, filename + ".java");

+        File parent = file.getParentFile();

+        parent.mkdirs();

+        

+        FileWriter wr = new FileWriter(file);

+        wr.write(source.getSource());

+        wr.close();

+    }

+

+    private static void removeSources() {

+        File file = new File(sourcepath);

+        removeFile(file);

+    }

+    

+    private static void removeFile(File file){

+        if(file.isDirectory()){

+            for(File f : file.listFiles()) removeFile(f);

+        }

+        file.delete();

+    }

+

+    private static RootDoc getRootDoc(Visibility visibility, java.util.Set<String> packages) throws IOException  {

+        long accessModifier = 0;

+        if(visibility == Visibility.PUBLIC){

+            accessModifier = 

+                com.sun.tools.javac.code.Flags.PUBLIC;    // 0x1

+        }

+        if(visibility == Visibility.PROTECTED){

+            accessModifier = 

+                com.sun.tools.javac.code.Flags.PUBLIC    // 0x1

+                | com.sun.tools.javac.code.Flags.PROTECTED;    // 0x4

+        }

+        if(visibility == Visibility.PACKAGE){

+            accessModifier = 

+                com.sun.tools.javac.code.Flags.PUBLIC    // 0x1

+                | com.sun.tools.javac.code.Flags.PROTECTED    // 0x4

+                | com.sun.tools.javadoc.ModifierFilter.PACKAGE; // 0x80000000

+        }

+        if(visibility == Visibility.PRIVATE){

+            accessModifier = 

+                com.sun.tools.javac.code.Flags.PUBLIC    // 0x1

+                | com.sun.tools.javac.code.Flags.PROTECTED    // 0x4

+                | com.sun.tools.javadoc.ModifierFilter.PACKAGE // 0x80000000

+                | com.sun.tools.javac.code.Flags.PRIVATE;    // 0x2

+        }

+

+        ModifierFilter showAccess = new ModifierFilter(accessModifier);

+        boolean breakiterator = false;

+        boolean quiet = false;

+        boolean legacy = false;

+        boolean docClasses = false;

+        

+        String docLocale = "";

+        String encoding = null;

+        ListBuffer<String> javaNames = new ListBuffer<String>();

+        for(String p : packages)

+            javaNames.append(p);

+        

+        ListBuffer<String[]> options = new ListBuffer<String[]>();

+    

+        

+//        String sourcepath = "//D:/Documents/Projects/08_CTS/signature-tools/signature-tools/test/";

+        options.append(new String[]{"-sourcepath", sourcepath});

+        

+        ListBuffer<String> subPackages = new ListBuffer<String>();

+        ListBuffer<String> excludedPackages = new ListBuffer<String>();

+

+        Context context = new Context();

+        Options compOpts = Options.instance(context);

+        compOpts.put("-sourcepath", sourcepath);

+        

+        Constructor<Messager> c;

+        try {

+//            c = Messager.class.getDeclaredConstructor(Context.class, String.class);

+//            c.setAccessible(true);

+//            c.newInstance(context, "SigTest");

+            c = Messager.class.getDeclaredConstructor(Context.class, String.class, PrintWriter.class, PrintWriter.class, PrintWriter.class);

+            c.setAccessible(true);

+            PrintWriter err = new PrintWriter(new StringWriter());

+            PrintWriter warn = new PrintWriter(new StringWriter());

+            PrintWriter notice = new PrintWriter(new StringWriter());

+            c.newInstance(context, "SigTest", err, warn, notice);

+        } catch (Exception e) {

+            throw new RuntimeException(e);

+        }

+

+        JavadocTool comp = JavadocTool.make0(context);

+        RootDocImpl root = comp.getRootDocImpl(docLocale, encoding, showAccess,

+                javaNames.toList(), options.toList(), breakiterator,

+                subPackages.toList(), excludedPackages.toList(), docClasses,

+                legacy, quiet);

+        return root;

+    }

+    

+}

diff --git a/tools/signature-tools/test/signature/converter/util/AbstractConvertTest.java b/tools/signature-tools/test/signature/converter/util/AbstractConvertTest.java
new file mode 100644
index 0000000..04935d8
--- /dev/null
+++ b/tools/signature-tools/test/signature/converter/util/AbstractConvertTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter.util;
+
+import java.io.IOException;
+import java.util.Set;
+
+import org.junit.Before;
+
+import signature.converter.Visibility;
+import signature.model.IApi;
+
+public abstract class AbstractConvertTest extends AbstractTestSourceConverter {
+    
+    private ITestSourceConverter converter;
+    
+    /**
+     * Creates and returns a converter instance.
+     * @return a converter instance
+     */
+    public abstract ITestSourceConverter createConverter();
+    
+    
+    @Before
+    public void setupConverter(){
+        converter = createConverter();
+    }
+
+    public IApi convert(Visibility visibility, Set<CompilationUnit> units) throws IOException {
+        return converter.convert(visibility, units);
+    }
+
+}
diff --git a/tools/signature-tools/test/signature/converter/util/AbstractTestSourceConverter.java b/tools/signature-tools/test/signature/converter/util/AbstractTestSourceConverter.java
new file mode 100644
index 0000000..5ca7422
--- /dev/null
+++ b/tools/signature-tools/test/signature/converter/util/AbstractTestSourceConverter.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter.util;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import signature.converter.Visibility;
+import signature.model.IApi;
+
+public abstract class AbstractTestSourceConverter implements ITestSourceConverter {
+
+    public IApi convert(Set<CompilationUnit> units) throws IOException {
+        return convert(Visibility.PROTECTED, units);
+    }
+    public IApi convert(CompilationUnit... units) throws IOException {
+        return convert(Visibility.PROTECTED, new HashSet<CompilationUnit>(Arrays.asList(units)));
+    }
+    public IApi convert(Visibility visibility, CompilationUnit... units) throws IOException {
+        return convert(visibility, new HashSet<CompilationUnit>(Arrays.asList(units)));
+    }
+}
+
diff --git a/tools/signature-tools/test/signature/converter/util/CompilationUnit.java b/tools/signature-tools/test/signature/converter/util/CompilationUnit.java
new file mode 100644
index 0000000..95960ae
--- /dev/null
+++ b/tools/signature-tools/test/signature/converter/util/CompilationUnit.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter.util;
+
+public class CompilationUnit {
+    
+    /** a.b.C */
+    private String name;
+    private String source;
+    
+    public CompilationUnit(String name, String source) {
+        this.name = name;
+        this.source = source;
+    }
+    
+    public String getName() {
+        return name;
+    }
+    
+    public String getSource() {
+        return source;
+    }
+}
diff --git a/tools/signature-tools/test/signature/converter/util/ITestSourceConverter.java b/tools/signature-tools/test/signature/converter/util/ITestSourceConverter.java
new file mode 100644
index 0000000..568a3e9
--- /dev/null
+++ b/tools/signature-tools/test/signature/converter/util/ITestSourceConverter.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * 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 signature.converter.util;
+
+import java.io.IOException;
+import java.util.Set;
+
+import signature.converter.Visibility;
+import signature.model.IApi;
+
+public interface ITestSourceConverter {
+    IApi convert(Set<CompilationUnit> units) throws IOException;
+    IApi convert(CompilationUnit... units) throws IOException;
+    IApi convert(Visibility visibility, Set<CompilationUnit> units) throws IOException;
+    IApi convert(Visibility visibility, CompilationUnit... units) throws IOException;
+}