AAPT2: Separate out the various steps

An early refactor. Some ideas became clearer as
development continued. Now the various phases are much
clearer and more easily reusable.

Also added a ton of tests!

Change-Id: Ic8f0a70c8222370352e63533b329c40457c0903e
diff --git a/tools/aapt2/ValueVisitor.h b/tools/aapt2/ValueVisitor.h
new file mode 100644
index 0000000..ee058aa
--- /dev/null
+++ b/tools/aapt2/ValueVisitor.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAPT_VALUE_VISITOR_H
+#define AAPT_VALUE_VISITOR_H
+
+#include "ResourceValues.h"
+
+namespace aapt {
+
+/**
+ * Visits a value and invokes the appropriate method based on its type. Does not traverse
+ * into compound types. Use ValueVisitor for that.
+ */
+struct RawValueVisitor {
+    virtual ~RawValueVisitor() = default;
+
+    virtual void visitItem(Item* value) {}
+    virtual void visit(Reference* value) { visitItem(value); }
+    virtual void visit(RawString* value) { visitItem(value); }
+    virtual void visit(String* value) { visitItem(value); }
+    virtual void visit(StyledString* value) { visitItem(value); }
+    virtual void visit(FileReference* value) { visitItem(value); }
+    virtual void visit(Id* value) { visitItem(value); }
+    virtual void visit(BinaryPrimitive* value) { visitItem(value); }
+
+    virtual void visit(Attribute* value) {}
+    virtual void visit(Style* value) {}
+    virtual void visit(Array* value) {}
+    virtual void visit(Plural* value) {}
+    virtual void visit(Styleable* value) {}
+};
+
+#define DECL_VISIT_COMPOUND_VALUE(T) \
+    virtual void visit(T* value) { \
+        visitSubValues(value); \
+    }
+
+/**
+ * Visits values, and if they are compound values, visits the components as well.
+ */
+struct ValueVisitor : public RawValueVisitor {
+    // The compiler will think we're hiding an overload, when we actually intend
+    // to call into RawValueVisitor. This will expose the visit methods in the super
+    // class so the compiler knows we are trying to call them.
+    using RawValueVisitor::visit;
+
+    void visitSubValues(Attribute* attribute) {
+        for (Attribute::Symbol& symbol : attribute->symbols) {
+            visit(&symbol.symbol);
+        }
+    }
+
+    void visitSubValues(Style* style) {
+        if (style->parent) {
+            visit(&style->parent.value());
+        }
+
+        for (Style::Entry& entry : style->entries) {
+            visit(&entry.key);
+            entry.value->accept(this);
+        }
+    }
+
+    void visitSubValues(Array* array) {
+        for (std::unique_ptr<Item>& item : array->items) {
+            item->accept(this);
+        }
+    }
+
+    void visitSubValues(Plural* plural) {
+        for (std::unique_ptr<Item>& item : plural->values) {
+            if (item) {
+                item->accept(this);
+            }
+        }
+    }
+
+    void visitSubValues(Styleable* styleable) {
+        for (Reference& reference : styleable->entries) {
+            visit(&reference);
+        }
+    }
+
+    DECL_VISIT_COMPOUND_VALUE(Attribute);
+    DECL_VISIT_COMPOUND_VALUE(Style);
+    DECL_VISIT_COMPOUND_VALUE(Array);
+    DECL_VISIT_COMPOUND_VALUE(Plural);
+    DECL_VISIT_COMPOUND_VALUE(Styleable);
+};
+
+/**
+ * Do not use directly. Helper struct for dyn_cast.
+ */
+template <typename T>
+struct DynCastVisitor : public RawValueVisitor {
+    T* value = nullptr;
+
+    void visit(T* v) override {
+        value = v;
+    }
+};
+
+/**
+ * Returns a valid pointer to T if the Value is of subtype T.
+ * Otherwise, returns nullptr.
+ */
+template <typename T>
+T* valueCast(Value* value) {
+    if (!value) {
+        return nullptr;
+    }
+    DynCastVisitor<T> visitor;
+    value->accept(&visitor);
+    return visitor.value;
+}
+
+} // namespace aapt
+
+#endif // AAPT_VALUE_VISITOR_H