auto import from //branches/cupcake_rel/...@138607
diff --git a/tools/test-progress-new/src/testprogress2/TestTargetNew.java b/tools/test-progress-new/src/testprogress2/TestTargetNew.java
new file mode 100644
index 0000000..6102614
--- /dev/null
+++ b/tools/test-progress-new/src/testprogress2/TestTargetNew.java
@@ -0,0 +1,373 @@
+/*
+ * 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.
+ */
+
+package testprogress2;
+
+import com.sun.javadoc.AnnotationDesc;
+import com.sun.javadoc.AnnotationValue;
+import com.sun.javadoc.ClassDoc;
+import com.sun.javadoc.ExecutableMemberDoc;
+import com.sun.javadoc.FieldDoc;
+import com.sun.javadoc.Parameter;
+import com.sun.javadoc.ParameterizedType;
+import com.sun.javadoc.Type;
+import com.sun.javadoc.TypeVariable;
+import com.sun.javadoc.AnnotationDesc.ElementValuePair;
+
+import testprogress2.TestMethodInformation.Level;
+
+/**
+ * holder for a TestTargetNew annotation
+ */
+public class TestTargetNew {
+    private final Originator originator;
+
+    private Level level = null;
+
+    private String notes = null;
+
+    /*
+     * method or constructor of target class
+     */
+    private ExecutableMemberDoc targetMethod = null;
+
+    /*
+     * only set if the target points -only- to a class, not to a method. e.g for
+     * special "!..." targets
+     */
+    private ClassDoc targetClass = null;
+
+    /*
+     * read from annotation, e.g. foobar(java.lang.String)
+     */
+    private String readMethodSignature = null;
+
+    /*
+     * e.g. foobar
+     */
+    private String readMethodName = null;
+
+    /*
+     * read from annotation
+     */
+    private ClassDoc readTargetClass = null;
+
+    private boolean havingProblems = false;
+
+    private TestTargetNew(Originator originator) {
+        this.originator = originator;
+    }
+
+    /**
+     * @param originator the origin (class or method)
+     * @param ttn the annotation (testtargetnew)
+     * @param classLevelTargetClass the default target class as given in the
+     *            testtargetclass annotation
+     */
+    public TestTargetNew(Originator originator, AnnotationDesc ttn,
+            ClassDoc classLevelTargetClass) {
+        this.originator = originator;
+        parseTargetClassAndMethodSignature(ttn, classLevelTargetClass);
+        // post: readMethod, readMethodSignature and readTargetClass are now set
+
+        // test for artificial method targets
+        if (readMethodName.startsWith("!")) {
+            targetMethod = null;
+            targetClass = readTargetClass;
+            // level = Level.ADDITIONAL;
+            // notes already set
+            notes = "target: " + readMethodName
+                    + (notes != null ? ", " + "notes: " + notes : "");
+
+        } else if (level == Level.TODO) {
+            notes = "TODO :" + notes;
+            havingProblems = true;
+        } else {
+            // prepare method target:
+            // if the signature contains a "." then the prefix is used as a
+            // reference
+            // to an inner class. This is an alternative to using the clazz
+            // attribute in cases where the class is an inner protected class,
+            // because then the inner class is not visible for the compiler at
+            // the
+            // place of the annotation.
+            // e.g. clazz = Certificate.CertificateRep.class does not work,
+            // so we use clazz = Certificate.class (enclosing class), and method
+            // "Certificate.CertificateRep.<methodHere>", e.g.
+            // "CertificateRep.CertificateRep"
+            // to denote the constructor of the inner protected class
+            // CertificateRep
+            // within Certificate
+            int dotPos = readMethodName.lastIndexOf('.');
+            if (dotPos != -1) {
+                String prefixClassName = readMethodName.substring(0, dotPos);
+                readMethodName = readMethodName.substring(dotPos + 1);
+                ClassDoc[] iCs = readTargetClass.innerClasses();
+                for (ClassDoc iC : iCs) {
+                    if (iC.name().equals(prefixClassName)) {
+                        readTargetClass = iC;
+                        break;
+                    }
+                }
+            }
+
+            String methodAndSig = readMethodName + readMethodSignature;
+            ExecutableMemberDoc tmeth = findMethodSignatureIn(methodAndSig,
+                    readTargetClass);
+            // we need this double test for the note below
+            if (tmeth == null) {
+                // a) wrong signature or
+                // b) a testMethod in a superclass or superinterface, ok also
+                tmeth = findTargetMethodInSelfAndSupers(methodAndSig,
+                        readTargetClass);
+                if (tmeth != null) {
+                    if (notes == null)
+                        notes = "";
+                    notes += "- targetmethod (" + tmeth + ") was found in a "
+                            + "superclass/superinterface of the target<br>";
+                }
+            }
+            if (tmeth != null) {
+                // found
+                targetMethod = tmeth;
+            } else {
+                havingProblems = true;
+                notes = "From " + originator.asString()
+                        + " -> could not resolve " + "targetMethod for class "
+                        + readTargetClass + ", " + "annotation was:" + ttn
+                        + ", testMethodSig " + "= " + methodAndSig + "<br>";
+                System.err.println(">>> warning: " + notes);
+            }
+        }
+    }
+
+    private ExecutableMemberDoc findMethodSignatureIn(String sig,
+            ClassDoc targetClass) {
+        ExecutableMemberDoc targetMethod = null;
+        // find the matching method in the target class, check all methods
+        for (ExecutableMemberDoc mdoc : targetClass.methods()) {
+            if (equalsSignature(mdoc, sig)) {
+                return mdoc;
+            }
+        }
+        // check constructors, too
+        for (ExecutableMemberDoc mdoc : targetClass.constructors()) {
+            if (equalsSignature(mdoc, sig)) {
+                return mdoc;
+            }
+        }
+        return null;
+    }
+
+    private ExecutableMemberDoc findTargetMethodInSelfAndSupers(String sig,
+            ClassDoc targetClass) {
+        ExecutableMemberDoc mem = findMethodSignatureIn(sig, targetClass);
+        if (mem != null) {
+            return mem;
+        }
+
+        // else visit parent class or parent interface(s)
+        ClassDoc[] ifs = targetClass.interfaces();
+        for (int i = 0; i < ifs.length; i++) {
+            ClassDoc iface = ifs[i];
+            mem = findTargetMethodInSelfAndSupers(sig, iface);
+            if (mem != null) {
+                return mem;
+            }
+        }
+
+        ClassDoc superclass = targetClass.superclass();
+        if (superclass != null) {
+            mem = findTargetMethodInSelfAndSupers(sig, superclass);
+            if (mem != null) {
+                return mem;
+            }
+        }
+        return null;
+    }
+
+    private void parseTargetClassAndMethodSignature(AnnotationDesc targetAnnot,
+            ClassDoc targetClass) {
+        ElementValuePair[] pairs = targetAnnot.elementValues();
+        String methodName = null;
+        String args = "";
+        for (ElementValuePair kval : pairs) {
+            if (kval.element().name().equals("method")) {
+                methodName = (String)kval.value().value();
+            } else if (kval.element().name().equals("clazz")) {
+                // optional: a different target class than the test-class-level
+                // default.
+                Object obj = kval.value().value();
+                if (obj instanceof ClassDoc) {
+                    targetClass = (ClassDoc)obj;
+                } else if (obj instanceof ParameterizedType) {
+                    targetClass = ((ParameterizedType)obj).asClassDoc();
+                } else {
+                    throw new RuntimeException("annotation elem value is of "
+                            + "type " + obj.getClass().getName() + " target "
+                            + "annotation = " + targetAnnot);
+                }
+            } else if (kval.element().name().equals("args")) {
+                AnnotationValue[] vals = (AnnotationValue[])kval.value()
+                        .value();
+                for (int i = 0; i < vals.length; i++) {
+                    AnnotationValue arg = vals[i];
+                    String argV;
+                    // TODO: we should be able to use Type.asClassDoc() here
+                    if (arg.value() instanceof ClassDoc) {
+                        ClassDoc cd = (ClassDoc)arg.value();
+                        argV = cd.qualifiedName();
+                    } else { // primitive type or array type
+                        // is there a nicer way to do this?
+                        argV = arg.toString();
+                    }
+                    // strip .class out of args since signature does not contain
+                    // those
+                    if (argV.endsWith(".class")) {
+                        argV = argV.substring(0, argV.length() - 6);
+                    }
+                    args += (i > 0 ? "," : "") + argV;
+                }
+            } else if (kval.element().name().equals("level")) {
+                AnnotationValue lev = kval.value();
+                FieldDoc fd = (FieldDoc)lev.value();
+                String slevel = fd.name();
+
+                try {
+                    level = Enum.valueOf(Level.class, slevel);
+                } catch (IllegalArgumentException iae) {
+                    throw new RuntimeException("COMPILE ERROR!!! enum "
+                            + slevel + " used in targetMethod for class "
+                            + "\"+targetClass+\", "
+                            + "annotation was:\"+targetAnnot+\", "
+                            + "testMethod = \"+methodDoc.toString()");
+                }
+            } else if (kval.element().name().equals("notes")) {
+                notes = (String)kval.value().value();
+                if (notes.equals("")) {
+                    notes = null;
+                }
+            }
+        }
+
+        // String refSig = methodName + "(" + args + ")";
+        // both methodName and methodArgs != null because of Annotation
+        // definition
+        this.readTargetClass = targetClass;
+        this.readMethodSignature = "(" + args + ")";
+        this.readMethodName = methodName;
+    }
+
+    private boolean equalsSignature(ExecutableMemberDoc mdoc,
+            String refSignature) {
+        Parameter[] params = mdoc.parameters();
+        String targs = "";
+        for (int i = 0; i < params.length; i++) {
+            Parameter parameter = params[i];
+            // check for generic type types
+            Type ptype = parameter.type();
+
+            TypeVariable typeVar = ptype.asTypeVariable();
+            String ptname;
+            if (typeVar != null) {
+                ptname = "java.lang.Object"; // the default fallback
+                Type[] bounds = typeVar.bounds();
+                if (bounds.length > 0) {
+                    ClassDoc typeClass = bounds[0].asClassDoc();
+                    ptname = typeClass.qualifiedName();
+                }
+                String dim = ptype.dimension();
+                if (dim != null && dim.length() > 0) {
+                    ptname += dim;
+                }
+            } else {
+                // regular var
+                // ptname = parameter.type().qualifiedTypeName();
+                ptname = parameter.type().toString();
+
+                // System.out.println("quali:"+ptname);
+                // ptname = parameter.typeName();
+                // omit type signature
+                ptname = ptname.replaceAll("<.*>", "");
+            }
+            targs += (i > 0 ? "," : "") + ptname;
+        }
+
+        String methodName = mdoc.name();
+        int lastDot = methodName.lastIndexOf('.');
+        if (lastDot != -1) {
+            // we have a inner class constructor
+            // shrink the name to just name the constructor
+            methodName = methodName.substring(lastDot + 1);
+        }
+
+        String testSig = methodName + "(" + targs + ")";
+
+        // return testSig.equals(refSignature);
+        if (testSig.equals(refSignature)) {
+            // System.out.println("match!!!: ref = "+refSignature+",
+            // test = "+testSig);
+            return true;
+        } else {
+            // System.out.println("no match: ref = "+refSignature+",
+            // test = "+testSig);
+            return false;
+        }
+    }
+
+    public Level getLevel() {
+        return level;
+    }
+
+    public boolean isHavingProblems() {
+        return havingProblems;
+    }
+
+    public Originator getOriginator() {
+        return originator;
+    }
+
+    TestTargetNew cloneMe(String extraNote) {
+        TestTargetNew anew = new TestTargetNew(this.originator);
+        anew.level = this.level;
+        anew.notes = this.notes;
+        anew.targetMethod = this.targetMethod;
+        anew.readMethodSignature = this.readMethodSignature;
+        anew.readTargetClass = this.readTargetClass;
+
+        // mark indirectly tested method always as green, independent
+        // of the original status (to better estimate workload)
+        // anew.level = Level.COMPLETE;
+        anew.notes = extraNote + (notes != null ? ", " + notes : "");
+        return anew;
+    }
+
+    public ExecutableMemberDoc getTargetMethod() {
+        return targetMethod;
+    }
+
+    /**
+     * @return the class of the testtargetnew which method starts with "!", null
+     *         otherwise
+     */
+    public ClassDoc getTargetClass() {
+        return targetClass;
+    }
+
+    public String getNotes() {
+        return notes;
+    }
+}