summaryrefslogtreecommitdiffstats
path: root/tools/signature-tools
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-15 16:47:16 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-15 16:47:16 -0700
commitf8057104af9cae031b544e971a52adafa7c0d9e1 (patch)
tree5006cc488ffc7c1a63ab3c08f877a046a6f3f351 /tools/signature-tools
downloadplatform_cts-f8057104af9cae031b544e971a52adafa7c0d9e1.tar.gz
platform_cts-f8057104af9cae031b544e971a52adafa7c0d9e1.tar.bz2
platform_cts-f8057104af9cae031b544e971a52adafa7c0d9e1.zip
auto import from //branches/cupcake_rel/...@138607
Diffstat (limited to 'tools/signature-tools')
-rw-r--r--tools/signature-tools/Android.mk66
-rw-r--r--tools/signature-tools/README.txt55
-rw-r--r--tools/signature-tools/TODO.txt5
-rw-r--r--tools/signature-tools/lib/antlr-2.7.7.jarbin0 -> 445288 bytes
-rw-r--r--tools/signature-tools/lib/stringtemplate.jarbin0 -> 172023 bytes
-rwxr-xr-xtools/signature-tools/sig47
-rwxr-xr-xtools/signature-tools/sig-check114
-rwxr-xr-xtools/signature-tools/sig-create111
-rw-r--r--tools/signature-tools/spec/android.specbin0 -> 1616500 bytes
-rw-r--r--tools/signature-tools/src/signature/Main.java134
-rw-r--r--tools/signature-tools/src/signature/UsageException.java26
-rw-r--r--tools/signature-tools/src/signature/Version.java27
-rw-r--r--tools/signature-tools/src/signature/compare/ApiComparator.java1705
-rw-r--r--tools/signature-tools/src/signature/compare/IApiComparator.java39
-rw-r--r--tools/signature-tools/src/signature/compare/Main.java192
-rw-r--r--tools/signature-tools/src/signature/compare/model/DeltaType.java35
-rw-r--r--tools/signature-tools/src/signature/compare/model/IAnnotatableElementDelta.java34
-rw-r--r--tools/signature-tools/src/signature/compare/model/IAnnotationDelta.java36
-rw-r--r--tools/signature-tools/src/signature/compare/model/IAnnotationElementDelta.java33
-rw-r--r--tools/signature-tools/src/signature/compare/model/IAnnotationFieldDelta.java33
-rw-r--r--tools/signature-tools/src/signature/compare/model/IApiDelta.java35
-rw-r--r--tools/signature-tools/src/signature/compare/model/IArrayTypeDelta.java33
-rw-r--r--tools/signature-tools/src/signature/compare/model/IClassDefinitionDelta.java92
-rw-r--r--tools/signature-tools/src/signature/compare/model/IConstructorDelta.java27
-rw-r--r--tools/signature-tools/src/signature/compare/model/IDelta.java48
-rw-r--r--tools/signature-tools/src/signature/compare/model/IEnumConstantDelta.java27
-rw-r--r--tools/signature-tools/src/signature/compare/model/IExecutableMemberDelta.java53
-rw-r--r--tools/signature-tools/src/signature/compare/model/IFieldDelta.java25
-rw-r--r--tools/signature-tools/src/signature/compare/model/IGenericDeclarationDelta.java26
-rw-r--r--tools/signature-tools/src/signature/compare/model/IMemberDelta.java44
-rw-r--r--tools/signature-tools/src/signature/compare/model/IMethodDelta.java33
-rw-r--r--tools/signature-tools/src/signature/compare/model/IModifierDelta.java26
-rw-r--r--tools/signature-tools/src/signature/compare/model/IPackageDelta.java37
-rw-r--r--tools/signature-tools/src/signature/compare/model/IParameterDelta.java34
-rw-r--r--tools/signature-tools/src/signature/compare/model/IParameterizedTypeDelta.java51
-rw-r--r--tools/signature-tools/src/signature/compare/model/IPrimitiveTypeDelta.java27
-rw-r--r--tools/signature-tools/src/signature/compare/model/ITypeDefinitionDelta.java27
-rw-r--r--tools/signature-tools/src/signature/compare/model/ITypeReferenceDelta.java27
-rw-r--r--tools/signature-tools/src/signature/compare/model/ITypeVariableDefinitionDelta.java42
-rw-r--r--tools/signature-tools/src/signature/compare/model/ITypeVariableDeltas.java41
-rw-r--r--tools/signature-tools/src/signature/compare/model/IUpperBoundsDelta.java49
-rw-r--r--tools/signature-tools/src/signature/compare/model/IValueDelta.java24
-rw-r--r--tools/signature-tools/src/signature/compare/model/IWildcardTypeDelta.java40
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigAnnotationDelta.java42
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigAnnotationElementDelta.java40
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigAnnotationFieldDelta.java40
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigApiDelta.java40
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigArrayTypeDelta.java40
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigClassDefinitionDelta.java136
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigClassReferenceDelta.java28
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigConstructorDelta.java28
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigDelta.java130
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigEnumConstantDelta.java39
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigExecutableMemberDelta.java83
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigFieldDelta.java28
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigGenericDeclarationDelta.java29
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigMemberDelta.java62
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigMethodDelta.java39
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigModifierDelta.java28
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigPackageDelta.java52
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigParameterDelta.java51
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigParameterizedTypeDelta.java61
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigPrimitiveTypeDelta.java28
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigTypeDefinitionDelta.java28
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigTypeDelta.java28
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigTypeVariableDefinitionDelta.java52
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigTypeVariableReferenceDelta.java42
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigUpperBoundsDelta.java55
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigValueDelta.java26
-rw-r--r--tools/signature-tools/src/signature/compare/model/impl/SigWildcardTypeDelta.java49
-rw-r--r--tools/signature-tools/src/signature/compare/model/subst/ArrayTypeProjection.java56
-rw-r--r--tools/signature-tools/src/signature/compare/model/subst/ClassProjection.java175
-rw-r--r--tools/signature-tools/src/signature/compare/model/subst/ClassReferenceProjection.java56
-rw-r--r--tools/signature-tools/src/signature/compare/model/subst/ConstructorProjection.java33
-rw-r--r--tools/signature-tools/src/signature/compare/model/subst/ExecutableMemberProjection.java76
-rw-r--r--tools/signature-tools/src/signature/compare/model/subst/MethodProjection.java48
-rw-r--r--tools/signature-tools/src/signature/compare/model/subst/ParameterProjection.java50
-rw-r--r--tools/signature-tools/src/signature/compare/model/subst/ParameterizedTypeProjection.java89
-rw-r--r--tools/signature-tools/src/signature/compare/model/subst/ViewpointAdapter.java111
-rw-r--r--tools/signature-tools/src/signature/compare/model/subst/WildcardTypeProjection.java63
-rw-r--r--tools/signature-tools/src/signature/converter/Main.java77
-rw-r--r--tools/signature-tools/src/signature/converter/Visibility.java36
-rw-r--r--tools/signature-tools/src/signature/converter/dex/DexFactory.java54
-rw-r--r--tools/signature-tools/src/signature/converter/dex/DexToSigConverter.java938
-rw-r--r--tools/signature-tools/src/signature/converter/dex/DexUtil.java600
-rw-r--r--tools/signature-tools/src/signature/converter/dex/FieldPool.java86
-rw-r--r--tools/signature-tools/src/signature/converter/dex/GenericSignatureParser.java651
-rw-r--r--tools/signature-tools/src/signature/converter/dex/IClassInitializer.java23
-rw-r--r--tools/signature-tools/src/signature/converter/doclet/DocletFactory.java124
-rw-r--r--tools/signature-tools/src/signature/converter/doclet/DocletToSigConverter.java636
-rw-r--r--tools/signature-tools/src/signature/io/IApiDeltaExternalizer.java25
-rw-r--r--tools/signature-tools/src/signature/io/IApiExternalizer.java30
-rw-r--r--tools/signature-tools/src/signature/io/IApiLoader.java28
-rw-r--r--tools/signature-tools/src/signature/io/html/ApiOverviewPage.java72
-rw-r--r--tools/signature-tools/src/signature/io/html/ClassByNameComparator.java34
-rw-r--r--tools/signature-tools/src/signature/io/html/ClassOverviewPage.java205
-rw-r--r--tools/signature-tools/src/signature/io/html/ExecutableMemberComparator.java102
-rw-r--r--tools/signature-tools/src/signature/io/html/FieldByNameComparator.java43
-rw-r--r--tools/signature-tools/src/signature/io/html/HtmlDeltaExternalizer.java131
-rw-r--r--tools/signature-tools/src/signature/io/html/IEmitter.java21
-rw-r--r--tools/signature-tools/src/signature/io/html/PackageByNameComparator.java40
-rw-r--r--tools/signature-tools/src/signature/io/html/PackageOverviewPage.java75
-rw-r--r--tools/signature-tools/src/signature/io/html/TemplateStore.java58
-rw-r--r--tools/signature-tools/src/signature/io/impl/BinaryApi.java83
-rw-r--r--tools/signature-tools/src/signature/io/impl/ToStringExternalizer.java41
-rw-r--r--tools/signature-tools/src/signature/model/IAnnotatableElement.java39
-rw-r--r--tools/signature-tools/src/signature/model/IAnnotation.java42
-rw-r--r--tools/signature-tools/src/signature/model/IAnnotationElement.java52
-rw-r--r--tools/signature-tools/src/signature/model/IAnnotationField.java49
-rw-r--r--tools/signature-tools/src/signature/model/IApi.java58
-rw-r--r--tools/signature-tools/src/signature/model/IArrayType.java30
-rw-r--r--tools/signature-tools/src/signature/model/IClassDefinition.java142
-rw-r--r--tools/signature-tools/src/signature/model/IClassReference.java32
-rw-r--r--tools/signature-tools/src/signature/model/IConstructor.java23
-rw-r--r--tools/signature-tools/src/signature/model/IEnumConstant.java30
-rw-r--r--tools/signature-tools/src/signature/model/IExecutableMember.java56
-rw-r--r--tools/signature-tools/src/signature/model/IField.java46
-rw-r--r--tools/signature-tools/src/signature/model/IGenericDeclaration.java41
-rw-r--r--tools/signature-tools/src/signature/model/IMethod.java35
-rw-r--r--tools/signature-tools/src/signature/model/IPackage.java54
-rw-r--r--tools/signature-tools/src/signature/model/IParameter.java30
-rw-r--r--tools/signature-tools/src/signature/model/IParameterizedType.java64
-rw-r--r--tools/signature-tools/src/signature/model/IPrimitiveType.java41
-rw-r--r--tools/signature-tools/src/signature/model/ITypeDefinition.java25
-rw-r--r--tools/signature-tools/src/signature/model/ITypeReference.java23
-rw-r--r--tools/signature-tools/src/signature/model/ITypeVariableDefinition.java48
-rw-r--r--tools/signature-tools/src/signature/model/ITypeVariableReference.java31
-rw-r--r--tools/signature-tools/src/signature/model/IWildcardType.java44
-rw-r--r--tools/signature-tools/src/signature/model/Kind.java36
-rw-r--r--tools/signature-tools/src/signature/model/Modifier.java53
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigAnnotatableElement.java51
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigAnnotation.java68
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigAnnotationElement.java54
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigAnnotationField.java40
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigApi.java64
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigArrayType.java69
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigClassDefinition.java231
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigClassReference.java67
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigConstructor.java55
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigEnumConstant.java42
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigExecutableMember.java90
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigField.java74
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigMethod.java75
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigPackage.java61
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigParameter.java46
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigParameterizedType.java121
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigPrimitiveType.java49
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigTypeVariableDefinition.java72
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigTypeVariableReference.java56
-rw-r--r--tools/signature-tools/src/signature/model/impl/SigWildcardType.java98
-rw-r--r--tools/signature-tools/src/signature/model/impl/Uninitialized.java67
-rw-r--r--tools/signature-tools/src/signature/model/util/ITypeFactory.java103
-rw-r--r--tools/signature-tools/src/signature/model/util/ModelUtil.java172
-rw-r--r--tools/signature-tools/src/signature/model/util/TypePool.java205
-rw-r--r--tools/signature-tools/templates/ApiOverviewPage.st60
-rw-r--r--tools/signature-tools/templates/ClassChangedLink.st1
-rw-r--r--tools/signature-tools/templates/ClassOverviewPage.st131
-rw-r--r--tools/signature-tools/templates/ClassReferenceLink.st1
-rw-r--r--tools/signature-tools/templates/Common_meta.st12
-rw-r--r--tools/signature-tools/templates/DeltaTableRow.st8
-rw-r--r--tools/signature-tools/templates/Header.st21
-rw-r--r--tools/signature-tools/templates/Link.st1
-rw-r--r--tools/signature-tools/templates/ModelElementRow.st6
-rw-r--r--tools/signature-tools/templates/PackageAddedLink.st1
-rw-r--r--tools/signature-tools/templates/PackageChangedLink.st1
-rw-r--r--tools/signature-tools/templates/PackageOverviewPage.st39
-rw-r--r--tools/signature-tools/templates/SimpleTableRow.st5
-rw-r--r--tools/signature-tools/templates/Styles.st44
-rw-r--r--tools/signature-tools/templates/Table.st9
-rw-r--r--tools/signature-tools/templates/delta/deltas.stg149
-rw-r--r--tools/signature-tools/templates/model/model.stg135
-rw-r--r--tools/signature-tools/test/signature/comparator/AllDexTests.java61
-rw-r--r--tools/signature-tools/test/signature/comparator/AllDocletTests.java52
-rw-r--r--tools/signature-tools/test/signature/comparator/AnnotationCompareTest.java72
-rw-r--r--tools/signature-tools/test/signature/comparator/ClassCompareTest.java388
-rw-r--r--tools/signature-tools/test/signature/comparator/MethodCompareTests.java495
-rw-r--r--tools/signature-tools/test/signature/comparator/PackageCompareTest.java95
-rw-r--r--tools/signature-tools/test/signature/comparator/util/AbstractComparatorTest.java56
-rw-r--r--tools/signature-tools/test/signature/converter/AllDexTests.java78
-rw-r--r--tools/signature-tools/test/signature/converter/AllDocletTests.java71
-rw-r--r--tools/signature-tools/test/signature/converter/ConvertAnnotationTest.java761
-rw-r--r--tools/signature-tools/test/signature/converter/ConvertClassTest.java668
-rw-r--r--tools/signature-tools/test/signature/converter/ConvertEnumTest.java191
-rw-r--r--tools/signature-tools/test/signature/converter/ConvertPackageTest.java69
-rw-r--r--tools/signature-tools/test/signature/converter/ConvertParameterizedTypeTest.java115
-rw-r--r--tools/signature-tools/test/signature/converter/ConvertVisibilityTest.java173
-rw-r--r--tools/signature-tools/test/signature/converter/ConvertWildcardTest.java100
-rw-r--r--tools/signature-tools/test/signature/converter/dex/DexExternalizerTest.java40
-rw-r--r--tools/signature-tools/test/signature/converter/dex/DexTestConverter.java46
-rw-r--r--tools/signature-tools/test/signature/converter/dex/DexUtilTest.java95
-rw-r--r--tools/signature-tools/test/signature/converter/dex/GenericSignatureParserTest.java69
-rw-r--r--tools/signature-tools/test/signature/converter/doclet/DocletTestConverter.java182
-rw-r--r--tools/signature-tools/test/signature/converter/util/AbstractConvertTest.java47
-rw-r--r--tools/signature-tools/test/signature/converter/util/AbstractTestSourceConverter.java39
-rw-r--r--tools/signature-tools/test/signature/converter/util/CompilationUnit.java37
-rw-r--r--tools/signature-tools/test/signature/converter/util/ITestSourceConverter.java30
196 files changed, 17642 insertions, 0 deletions
diff --git a/tools/signature-tools/Android.mk b/tools/signature-tools/Android.mk
new file mode 100644
index 00000000000..cf9e053c645
--- /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 00000000000..b4198b9f1b5
--- /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 00000000000..fd20800e930
--- /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 00000000000..5e5f14b3558
--- /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 00000000000..8e415319628
--- /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 00000000000..19b57fa2004
--- /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 00000000000..0c1cbcee5c1
--- /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 00000000000..4049e69912b
--- /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 00000000000..fbbf53aaaba
--- /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 00000000000..5b1c9ff8b13
--- /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 00000000000..6cdf9cf84bc
--- /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 00000000000..d20e81fcc5a
--- /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 00000000000..9232d2da804
--- /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 00000000000..08ed97fd963
--- /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 00000000000..80edb4536fd
--- /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 00000000000..a3aad2c0eb0
--- /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 00000000000..dd41c601f47
--- /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 00000000000..2e29358b6c4
--- /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 00000000000..4355fdb9049
--- /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 00000000000..223072a3837
--- /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 00000000000..78a8c34e2fd
--- /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 00000000000..bb29bcda2aa
--- /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 00000000000..5cbaf9b283a
--- /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 00000000000..64ba993faa9
--- /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 00000000000..bd94388fcd4
--- /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 00000000000..6590c5a8f86
--- /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 00000000000..30f7038ceec
--- /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 00000000000..ab9bf766d73
--- /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 00000000000..5cd518c5ff3
--- /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 00000000000..df78307f54a
--- /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 00000000000..3e94d263045
--- /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 00000000000..4553e1092e7
--- /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 00000000000..8c697c3d9ba
--- /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 00000000000..b2a6a80f041
--- /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 00000000000..be54a01b6e4
--- /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 00000000000..f7294359dd2
--- /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 00000000000..932cc39be3c
--- /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 00000000000..fba52f0a3c7
--- /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 00000000000..1e8f3cd803e
--- /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 00000000000..a88ea306126
--- /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 00000000000..44bd39a9aba
--- /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 00000000000..abd1f59fe61
--- /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 00000000000..1fda09c180a
--- /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 00000000000..78e515f2198
--- /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 00000000000..cc7a6fcc7f7
--- /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 00000000000..90fcd7b38a2
--- /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 00000000000..bc2bd56cae8
--- /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 00000000000..5d472933bf6
--- /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 00000000000..40343518781
--- /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 00000000000..18741ebea44
--- /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 00000000000..9a7cf70ac77
--- /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 00000000000..933bf002035
--- /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 00000000000..3a7f9e72d70
--- /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 00000000000..1d871e41e46
--- /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 00000000000..6807eea8db0
--- /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 00000000000..d377b9501cd
--- /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 00000000000..2c5e9cb57b1
--- /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 00000000000..0a3fb2fc70f
--- /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 00000000000..aa5e380b137
--- /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 00000000000..0f368f6e685
--- /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 00000000000..aee6466e88a
--- /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 00000000000..08fbc219502
--- /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 00000000000..03be8fa307b
--- /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 00000000000..c0bff8e53dc
--- /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 00000000000..718258ca994
--- /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 00000000000..348c728c09b
--- /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 00000000000..4414a16ecd7
--- /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 00000000000..8822b260715
--- /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 00000000000..9521f0e2786
--- /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 00000000000..e6cafcba33f
--- /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 00000000000..428146e7ed8
--- /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 00000000000..630d1027401
--- /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 00000000000..648ccf85f40
--- /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 00000000000..1ffd61671f8
--- /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 00000000000..f96ac543fb1
--- /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 00000000000..c98fb09bd53
--- /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 00000000000..9c48ab7d032
--- /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 00000000000..59836db1ea7
--- /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 00000000000..88f457fc6ba
--- /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 00000000000..a59873cdb0a
--- /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 00000000000..f426877272d
--- /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 00000000000..653c61798d3
--- /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 00000000000..b7cc00ea1d5
--- /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 00000000000..13312bdbf2c
--- /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 00000000000..f661af2ae42
--- /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 00000000000..6587820b8ab
--- /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 00000000000..773e2fc72ff
--- /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 00000000000..935ca49aef2
--- /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 00000000000..ea757dbedde
--- /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 00000000000..f9ebe77545c
--- /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 00000000000..bf3cb8b2328
--- /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 00000000000..3bbfbe5b37e
--- /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 00000000000..a38fa1a473f
--- /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 00000000000..d97c0924a19
--- /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 00000000000..8e2343453af
--- /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 00000000000..6951fb33a89
--- /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 00000000000..e3423421543
--- /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 00000000000..9aaf1f8871c
--- /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 00000000000..1ba5cba2c8f
--- /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 00000000000..db73e6617e1
--- /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 00000000000..3bbff71d29b
--- /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 00000000000..ccfe3cc7caf
--- /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 00000000000..a161bf79069
--- /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 00000000000..f12cf6a7784
--- /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 00000000000..62615af181d
--- /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 00000000000..53d6c385aee
--- /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 00000000000..c31689deef0
--- /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 00000000000..5637fd64e27
--- /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 00000000000..c40707f8d0f
--- /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 00000000000..de51938fdae
--- /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 00000000000..bb63e67c700
--- /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 00000000000..1bd5401462d
--- /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 00000000000..bcb2c555a49
--- /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 00000000000..29f52758574
--- /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 00000000000..681e62b39ab
--- /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 00000000000..ef7f7ba84bc
--- /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 00000000000..3cf759319ce
--- /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 00000000000..d7f4683e69f
--- /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 00000000000..e205db15f9d
--- /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 00000000000..78b14cea876
--- /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 00000000000..bd359d54dee
--- /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 00000000000..59f5692b951
--- /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 00000000000..917b96b7262
--- /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 00000000000..b182f217527
--- /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 00000000000..f17f1725093
--- /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 00000000000..df0ead05b43
--- /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 00000000000..64e0657b400
--- /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 00000000000..02a0d2def2a
--- /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 00000000000..219e039e486
--- /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 00000000000..223e88f7db2
--- /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 00000000000..53f021ea282
--- /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 00000000000..b7d0354c371
--- /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 00000000000..3d676a77ccb
--- /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 00000000000..5dd6faf0c47
--- /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 00000000000..b573f8fa52a
--- /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 00000000000..3d20824e312
--- /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 00000000000..fe7c7ab5593
--- /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 00000000000..d4336dec7c4
--- /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 00000000000..1da30260946
--- /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 00000000000..2878988a6e0
--- /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 00000000000..3203d5957e7
--- /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 00000000000..e3055667019
--- /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 00000000000..489397f3411
--- /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 00000000000..686917ca275
--- /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 00000000000..d9d33698185
--- /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 00000000000..d72613548fd
--- /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 00000000000..27861694a93
--- /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 00000000000..e0f918e425b
--- /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 00000000000..6bd25936448
--- /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 00000000000..c24ac238863
--- /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 00000000000..cc88479a178
--- /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 00000000000..af3e3a9413a
--- /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 00000000000..f66fd2c0f5e
--- /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 00000000000..dc481137f03
--- /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 00000000000..4faa1935aa9
--- /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 00000000000..20e0ed98e9e
--- /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 00000000000..45b4c1c67fe
--- /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 00000000000..c22e9b5b3dc
--- /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 00000000000..86637815b35
--- /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 00000000000..4d0974ce736
--- /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 00000000000..9aa8e2fbddd
--- /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 00000000000..242109424e2
--- /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 00000000000..54b20c6f511
--- /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 00000000000..eb352da0306
--- /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 00000000000..5951f2ab881
--- /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 00000000000..ebeded0b54d
--- /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 00000000000..3e7e7c2e215
--- /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 00000000000..4294eb31dd4
--- /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 00000000000..2eecb8eaf7a
--- /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 00000000000..a27d64129a4
--- /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 00000000000..425ad36bf3d
--- /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 00000000000..b44dcb6b1f2
--- /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 00000000000..327d93139e8
--- /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 00000000000..c72b6372821
--- /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 00000000000..71719780edc
--- /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 00000000000..3e94506d472
--- /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 00000000000..d522186226b
--- /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 00000000000..6392dc9d036
--- /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 00000000000..84d26a895bf
--- /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 00000000000..610917efd56
--- /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 00000000000..f53f40347cc
--- /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 00000000000..5bcdcb44f17
--- /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 00000000000..98ebd612fec
--- /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 00000000000..edd2a41c6a0
--- /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 00000000000..653d42f6313
--- /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 00000000000..09fc32f1fc9
--- /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 00000000000..d18c568d63c
--- /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 00000000000..8e27da52704
--- /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 00000000000..b6b90fa4a04
--- /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 00000000000..ff005fb78d1
--- /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 00000000000..52d73f8955c
--- /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 00000000000..8e867ddb469
--- /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 00000000000..04935d8ebb1
--- /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 00000000000..5ca7422f080
--- /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 00000000000..95960aef0ac
--- /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 00000000000..568a3e9bc37
--- /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;
+}