11b9940e612fc73202837fbe9db2f9035f307b5d1George Mount/*
21b9940e612fc73202837fbe9db2f9035f307b5d1George Mount * Copyright (C) 2015 The Android Open Source Project
31b9940e612fc73202837fbe9db2f9035f307b5d1George Mount *
41b9940e612fc73202837fbe9db2f9035f307b5d1George Mount * Licensed under the Apache License, Version 2.0 (the "License");
51b9940e612fc73202837fbe9db2f9035f307b5d1George Mount * you may not use this file except in compliance with the License.
61b9940e612fc73202837fbe9db2f9035f307b5d1George Mount * You may obtain a copy of the License at
71b9940e612fc73202837fbe9db2f9035f307b5d1George Mount *
81b9940e612fc73202837fbe9db2f9035f307b5d1George Mount *      http://www.apache.org/licenses/LICENSE-2.0
91b9940e612fc73202837fbe9db2f9035f307b5d1George Mount *
101b9940e612fc73202837fbe9db2f9035f307b5d1George Mount * Unless required by applicable law or agreed to in writing, software
111b9940e612fc73202837fbe9db2f9035f307b5d1George Mount * distributed under the License is distributed on an "AS IS" BASIS,
121b9940e612fc73202837fbe9db2f9035f307b5d1George Mount * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131b9940e612fc73202837fbe9db2f9035f307b5d1George Mount * See the License for the specific language governing permissions and
141b9940e612fc73202837fbe9db2f9035f307b5d1George Mount * limitations under the License.
151b9940e612fc73202837fbe9db2f9035f307b5d1George Mount */
16fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountpackage android.databinding.tool.reflection;
171b9940e612fc73202837fbe9db2f9035f307b5d1George Mount
18fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.annotation.AnnotationAnalyzer;
19fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.util.L;
202611838bffef5a009ca71e3e9e59a93f29b098edYigit Boyarimport android.databinding.tool.util.Preconditions;
21fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount
22a7e767e576adebcddf043ad34ccb8dd167f777b3George Mountimport java.util.Map;
23fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount
241b9940e612fc73202837fbe9db2f9035f307b5d1George Mountimport javax.annotation.processing.ProcessingEnvironment;
251b9940e612fc73202837fbe9db2f9035f307b5d1George Mount
26fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount/**
27fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount * This is the base class for several implementations of something that
28fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount * acts like a ClassLoader. Different implementations work with the Annotation
29fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount * Processor, ClassLoader, and an Android Studio plugin.
30fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount */
3179fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mountpublic abstract class ModelAnalyzer {
3297d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar
3397d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    public static final String[] LIST_CLASS_NAMES = {
3497d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar            "java.util.List",
3597d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar            "android.util.SparseArray",
3697d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar            "android.util.SparseBooleanArray",
3797d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar            "android.util.SparseIntArray",
3897d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar            "android.util.SparseLongArray",
3997d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar            "android.util.LongSparseArray",
4097d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar            "android.support.v4.util.LongSparseArray",
4197d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    };
4297d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar
4397d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    public static final String MAP_CLASS_NAME = "java.util.Map";
4497d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar
4597d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    public static final String STRING_CLASS_NAME = "java.lang.String";
4697d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar
4797d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    public static final String OBJECT_CLASS_NAME = "java.lang.Object";
4897d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar
49fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount    public static final String OBSERVABLE_CLASS_NAME = "android.databinding.Observable";
5097d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar
51fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount    public static final String OBSERVABLE_LIST_CLASS_NAME = "android.databinding.ObservableList";
5297d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar
53fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount    public static final String OBSERVABLE_MAP_CLASS_NAME = "android.databinding.ObservableMap";
5497d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar
5597d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    public static final String[] OBSERVABLE_FIELDS = {
56fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            "android.databinding.ObservableBoolean",
57fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            "android.databinding.ObservableByte",
58fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            "android.databinding.ObservableChar",
59fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            "android.databinding.ObservableShort",
60fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            "android.databinding.ObservableInt",
61fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            "android.databinding.ObservableLong",
62fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            "android.databinding.ObservableFloat",
63fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            "android.databinding.ObservableDouble",
64fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            "android.databinding.ObservableField",
65d37b47419005587c52ca4c099432327b7f06478dYigit Boyar            "android.databinding.ObservableParcelable",
6697d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    };
6797d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar
684c5cc009bcbcfb19e33fb19db5ec80f83f7b3326George Mount    public static final String VIEW_DATA_BINDING =
69fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount            "android.databinding.ViewDataBinding";
7097d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar
71de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    public static final String VIEW_STUB_CLASS_NAME = "android.view.ViewStub";
72de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
73fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    private ModelClass[] mListTypes;
74fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    private ModelClass mMapType;
75fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    private ModelClass mStringType;
76fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    private ModelClass mObjectType;
77fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    private ModelClass mObservableType;
78fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    private ModelClass mObservableListType;
79fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    private ModelClass mObservableMapType;
80fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    private ModelClass[] mObservableFieldTypes;
81fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    private ModelClass mViewBindingType;
82de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    private ModelClass mViewStubType;
83fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount
8479fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    private static ModelAnalyzer sAnalyzer;
851b9940e612fc73202837fbe9db2f9035f307b5d1George Mount
8697d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    protected void setInstance(ModelAnalyzer analyzer) {
8797d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        sAnalyzer = analyzer;
8897d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    }
8997d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar
9079fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    public ModelClass findCommonParentOf(ModelClass modelClass1,
9179fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount            ModelClass modelClass2) {
9279fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        ModelClass curr = modelClass1;
9379fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        while (curr != null && !curr.isAssignableFrom(modelClass2)) {
9479fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount            curr = curr.getSuperclass();
951b9940e612fc73202837fbe9db2f9035f307b5d1George Mount        }
9679fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        if (curr == null) {
9791beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount            if (modelClass1.isObject() && modelClass2.isInterface()) {
9891beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount                return modelClass1;
9991beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount            } else if (modelClass2.isObject() && modelClass1.isInterface()) {
10091beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount                return modelClass2;
10191beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount            }
10291beb3a1a89a58b1c0b6b874d889394a3be90b6cGeorge Mount
10379fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount            ModelClass primitive1 = modelClass1.unbox();
10479fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount            ModelClass primitive2 = modelClass2.unbox();
10579fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount            if (!modelClass1.equals(primitive1) || !modelClass2.equals(primitive2)) {
10679fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount                return findCommonParentOf(primitive1, primitive2);
1071b9940e612fc73202837fbe9db2f9035f307b5d1George Mount            }
1081b9940e612fc73202837fbe9db2f9035f307b5d1George Mount        }
10979fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        Preconditions.checkNotNull(curr,
11079fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount                "must be able to find a common parent for " + modelClass1 + " and " + modelClass2);
11179fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        return curr;
1121b9940e612fc73202837fbe9db2f9035f307b5d1George Mount
1131b9940e612fc73202837fbe9db2f9035f307b5d1George Mount    }
1141b9940e612fc73202837fbe9db2f9035f307b5d1George Mount
11579fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    public abstract ModelClass loadPrimitive(String className);
1161b9940e612fc73202837fbe9db2f9035f307b5d1George Mount
11779fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    public static ModelAnalyzer getInstance() {
11879fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        return sAnalyzer;
1191b9940e612fc73202837fbe9db2f9035f307b5d1George Mount    }
1201b9940e612fc73202837fbe9db2f9035f307b5d1George Mount
12179fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    public static void setProcessingEnvironment(ProcessingEnvironment processingEnvironment) {
12297d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        if (sAnalyzer != null) {
12397d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar            throw new IllegalStateException("processing env is already created, you cannot "
12497d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar                    + "change class loader after that");
12597d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        }
12697d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        L.d("setting processing env to %s", processingEnvironment);
12779fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        AnnotationAnalyzer annotationAnalyzer = new AnnotationAnalyzer(processingEnvironment);
12879fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        sAnalyzer = annotationAnalyzer;
1291b9940e612fc73202837fbe9db2f9035f307b5d1George Mount    }
1301b9940e612fc73202837fbe9db2f9035f307b5d1George Mount
131895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar    /**
132895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar     * Takes a raw className (potentially w/ generics and arrays) and expands definitions using
133895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar     * the import statements.
134895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar     * <p>
135895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar     * For instance, this allows user to define variables
136895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar     * <variable type="User" name="user"/>
137895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar     * if they previously imported User.
138895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar     * <import name="com.example.User"/>
139895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar     */
140895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar    public String applyImports(String className, Map<String, String> imports) {
141895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        className = className.trim();
142895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        int numDimensions = 0;
143895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        String generic = null;
144895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        // handle array
145895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        while (className.endsWith("[]")) {
146895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            numDimensions++;
147895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            className = className.substring(0, className.length() - 2);
148895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        }
149895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        // handle generics
150895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        final int lastCharIndex = className.length() - 1;
151895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        if ('>' == className.charAt(lastCharIndex)) {
152895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            // has generic.
153895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            int open = className.indexOf('<');
154895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            if (open == -1) {
155895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar                L.e("un-matching generic syntax for %s", className);
156895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar                return className;
157895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            }
158895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            generic = applyImports(className.substring(open + 1, lastCharIndex), imports);
159895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            className = className.substring(0, open);
160895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        }
161895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        int dotIndex = className.indexOf('.');
162895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        final String qualifier;
163895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        final String rest;
164895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        if (dotIndex == -1) {
165895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            qualifier = className;
166895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            rest = null;
167895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        } else {
168895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            qualifier = className.substring(0, dotIndex);
169895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            rest = className.substring(dotIndex); // includes dot
170895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        }
171895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        final String expandedQualifier = imports.get(qualifier);
172895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        String result;
173895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        if (expandedQualifier != null) {
174895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            result = rest == null ? expandedQualifier : expandedQualifier + rest;
175895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        } else {
176895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            result = className; // no change
177895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        }
178895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        // now append back dimension and generics
179895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        if (generic != null) {
180895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            result = result + "<" + applyImports(generic, imports) + ">";
181895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        }
182895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        while (numDimensions-- > 0) {
183895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            result = result + "[]";
184895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        }
185895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        return result;
186895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar    }
187895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar
18879fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    public String getDefaultValue(String className) {
18997d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        if ("int".equals(className)) {
19079fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount            return "0";
1911b9940e612fc73202837fbe9db2f9035f307b5d1George Mount        }
19297d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        if ("short".equals(className)) {
19379fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount            return "0";
1941b9940e612fc73202837fbe9db2f9035f307b5d1George Mount        }
19597d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        if ("long".equals(className)) {
19679fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount            return "0L";
1971b9940e612fc73202837fbe9db2f9035f307b5d1George Mount        }
19897d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        if ("float".equals(className)) {
19979fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount            return "0f";
2001b9940e612fc73202837fbe9db2f9035f307b5d1George Mount        }
20197d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        if ("double".equals(className)) {
20279fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount            return "0.0";
2031b9940e612fc73202837fbe9db2f9035f307b5d1George Mount        }
20497d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar        if ("boolean".equals(className)) {
20579fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount            return "false";
2061b9940e612fc73202837fbe9db2f9035f307b5d1George Mount        }
20779fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        if ("char".equals(className)) {
20879fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount            return "'\\u0000'";
2091b9940e612fc73202837fbe9db2f9035f307b5d1George Mount        }
21079fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        if ("byte".equals(className)) {
21179fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount            return "0";
2121b9940e612fc73202837fbe9db2f9035f307b5d1George Mount        }
21379fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount        return "null";
2141b9940e612fc73202837fbe9db2f9035f307b5d1George Mount    }
2151b9940e612fc73202837fbe9db2f9035f307b5d1George Mount
216a7e767e576adebcddf043ad34ccb8dd167f777b3George Mount    public abstract ModelClass findClass(String className, Map<String, String> imports);
2171b9940e612fc73202837fbe9db2f9035f307b5d1George Mount
21879fc7f3727815ab35bb1bb2e060bfb7db3176eedGeorge Mount    public abstract ModelClass findClass(Class classType);
21997d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar
22097d6ddf47f4ff1abb3ed5201ce5232163f5325b1Yigit Boyar    public abstract TypeUtil createTypeUtil();
221fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount
222fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    ModelClass[] getListTypes() {
223fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        if (mListTypes == null) {
224fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount            mListTypes = new ModelClass[LIST_CLASS_NAMES.length];
225fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount            for (int i = 0; i < mListTypes.length; i++) {
226fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount                final ModelClass modelClass = findClass(LIST_CLASS_NAMES[i], null);
227fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount                if (modelClass != null) {
228fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount                    mListTypes[i] = modelClass.erasure();
229fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount                }
230fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount            }
231fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        }
232fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        return mListTypes;
233fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    }
234fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount
235fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    public ModelClass getMapType() {
236fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        if (mMapType == null) {
237fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount            mMapType = loadClassErasure(MAP_CLASS_NAME);
238fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        }
239fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        return mMapType;
240fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    }
241fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount
242fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    ModelClass getStringType() {
243fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        if (mStringType == null) {
244fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount            mStringType = findClass(STRING_CLASS_NAME, null);
245fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        }
246fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        return mStringType;
247fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    }
248fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount
249fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    ModelClass getObjectType() {
250fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        if (mObjectType == null) {
251fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount            mObjectType = findClass(OBJECT_CLASS_NAME, null);
252fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        }
253fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        return mObjectType;
254fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    }
255fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount
256fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    ModelClass getObservableType() {
257fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        if (mObservableType == null) {
258fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount            mObservableType = findClass(OBSERVABLE_CLASS_NAME, null);
259fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        }
260fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        return mObservableType;
261fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    }
262fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount
263fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    ModelClass getObservableListType() {
264fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        if (mObservableListType == null) {
265fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount            mObservableListType = loadClassErasure(OBSERVABLE_LIST_CLASS_NAME);
266fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        }
267fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        return mObservableListType;
268fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    }
269fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount
270fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    ModelClass getObservableMapType() {
271fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        if (mObservableMapType == null) {
272fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount            mObservableMapType = loadClassErasure(OBSERVABLE_MAP_CLASS_NAME);
273fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        }
274fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        return mObservableMapType;
275fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    }
276fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount
277fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    ModelClass getViewDataBindingType() {
278fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        if (mViewBindingType == null) {
279fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount            mViewBindingType = findClass(VIEW_DATA_BINDING, null);
280fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        }
281fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        return mViewBindingType;
282fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    }
283fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount
284924fa7c597694ebc433fc0379d0015785351d1b7Yigit Boyar    protected ModelClass[] getObservableFieldTypes() {
285fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        if (mObservableFieldTypes == null) {
286fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount            mObservableFieldTypes = new ModelClass[OBSERVABLE_FIELDS.length];
287fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount            for (int i = 0; i < OBSERVABLE_FIELDS.length; i++) {
288fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount                mObservableFieldTypes[i] = loadClassErasure(OBSERVABLE_FIELDS[i]);
289fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount            }
290fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        }
291fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        return mObservableFieldTypes;
292fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    }
293fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount
294de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    ModelClass getViewStubType() {
295de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        if (mViewStubType == null) {
296de38dd3ef0577d25b2d59863603abe5750d0c231George Mount            mViewStubType = findClass(VIEW_STUB_CLASS_NAME, null);
297de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        }
298de38dd3ef0577d25b2d59863603abe5750d0c231George Mount        return mViewStubType;
299de38dd3ef0577d25b2d59863603abe5750d0c231George Mount    }
300de38dd3ef0577d25b2d59863603abe5750d0c231George Mount
301fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    private ModelClass loadClassErasure(String className) {
302fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount        return findClass(className, null).erasure();
303fa9fe12980ef1103fabe33bf5ff0e2f53042a204George Mount    }
3041b9940e612fc73202837fbe9db2f9035f307b5d1George Mount}
305