[go: nahoru, domu]

13bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar/*
23bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar * Copyright (C) 2015 The Android Open Source Project
33bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
43bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar * you may not use this file except in compliance with the License.
53bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar * You may obtain a copy of the License at
63bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
73bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar * Unless required by applicable law or agreed to in writing, software
83bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
93bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
103bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar * See the License for the specific language governing permissions and
113bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar * limitations under the License.
123bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar */
133bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
14fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountpackage android.databinding.tool.store;
153bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
16aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyarimport android.databinding.tool.processing.ErrorMessages;
17aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyarimport android.databinding.tool.processing.Scope;
18aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyarimport android.databinding.tool.processing.ScopedException;
19aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyarimport android.databinding.tool.processing.scopes.FileScopeProvider;
20731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport android.databinding.tool.processing.scopes.LocationScopeProvider;
21fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.util.L;
22fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.util.ParserHelper;
23c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyarimport android.databinding.tool.util.Preconditions;
243bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
25731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport java.io.File;
2628e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyarimport java.io.InputStream;
27b134dd773c386246ee8b692fbc4f063945e88ec5Yigit Boyarimport java.io.Serializable;
2828e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyarimport java.io.StringWriter;
293bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyarimport java.util.ArrayList;
30731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport java.util.Arrays;
313bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyarimport java.util.HashMap;
323bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyarimport java.util.HashSet;
333bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyarimport java.util.List;
343bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyarimport java.util.Map;
353bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyarimport java.util.Set;
363bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
3728e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyarimport javax.xml.bind.JAXBContext;
3828e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyarimport javax.xml.bind.JAXBException;
3928e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyarimport javax.xml.bind.Marshaller;
4028e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyarimport javax.xml.bind.Unmarshaller;
418e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport javax.xml.bind.annotation.XmlAccessType;
428e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport javax.xml.bind.annotation.XmlAccessorType;
438e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport javax.xml.bind.annotation.XmlAttribute;
448e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport javax.xml.bind.annotation.XmlElement;
458e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport javax.xml.bind.annotation.XmlElementWrapper;
468e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mountimport javax.xml.bind.annotation.XmlRootElement;
478e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount
483bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar/**
493bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar * This is a serializable class that can keep the result of parsing layout files.
503bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar */
51b134dd773c386246ee8b692fbc4f063945e88ec5Yigit Boyarpublic class ResourceBundle implements Serializable {
52a97508c49c11bbc92722192890ca43a3bf6d3036Yigit Boyar    private static final String[] ANDROID_VIEW_PACKAGE_VIEWS = new String[]
53a97508c49c11bbc92722192890ca43a3bf6d3036Yigit Boyar            {"View", "ViewGroup", "ViewStub", "TextureView", "SurfaceView"};
543bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar    private String mAppPackage;
553bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
56895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar    private HashMap<String, List<LayoutFileBundle>> mLayoutBundles
57895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            = new HashMap<String, List<LayoutFileBundle>>();
583bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
599784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar    private List<File> mRemovedFiles = new ArrayList<File>();
609784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar
618e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount    public ResourceBundle(String appPackage) {
628e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        mAppPackage = appPackage;
638e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount    }
648e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount
650390898cf7c4fcad255e8cfd6802f722b516cb2cGeorge Mount    public void addLayoutBundle(LayoutFileBundle bundle) {
660c2ed0cbaee2f206e926bfc780b05e9f1e52b551Yigit Boyar        if (bundle.mFileName == null) {
670c2ed0cbaee2f206e926bfc780b05e9f1e52b551Yigit Boyar            L.e("File bundle must have a name. %s does not have one.", bundle);
680c2ed0cbaee2f206e926bfc780b05e9f1e52b551Yigit Boyar            return;
690c2ed0cbaee2f206e926bfc780b05e9f1e52b551Yigit Boyar        }
703bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        if (!mLayoutBundles.containsKey(bundle.mFileName)) {
713bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            mLayoutBundles.put(bundle.mFileName, new ArrayList<LayoutFileBundle>());
723bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
73a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        final List<LayoutFileBundle> bundles = mLayoutBundles.get(bundle.mFileName);
74a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        for (LayoutFileBundle existing : bundles) {
75a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            if (existing.equals(bundle)) {
76a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                L.d("skipping layout bundle %s because it already exists.", bundle);
77a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                return;
78a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            }
79a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        }
80a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        L.d("adding bundle %s", bundle);
81a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        bundles.add(bundle);
823bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar    }
833bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
843bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar    public HashMap<String, List<LayoutFileBundle>> getLayoutBundles() {
853bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        return mLayoutBundles;
863bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar    }
873bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
883bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar    public String getAppPackage() {
893bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        return mAppPackage;
903bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar    }
913bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
923bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar    public void validateMultiResLayouts() {
937ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        for (List<LayoutFileBundle> layoutFileBundles : mLayoutBundles.values()) {
947ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            for (LayoutFileBundle layoutFileBundle : layoutFileBundles) {
959784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar                List<BindingTargetBundle> unboundIncludes = new ArrayList<BindingTargetBundle>();
967ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                for (BindingTargetBundle target : layoutFileBundle.getBindingTargetBundles()) {
977ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                    if (target.isBinder()) {
987ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                        List<LayoutFileBundle> boundTo =
997ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                                mLayoutBundles.get(target.getIncludedLayout());
1007ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                        if (boundTo == null || boundTo.isEmpty()) {
1018510dab6a17ccd59a2a9cbc07f900dfc2f11ff2bGeorge Mount                            L.d("There is no binding for %s, reverting to plain layout",
1028510dab6a17ccd59a2a9cbc07f900dfc2f11ff2bGeorge Mount                                    target.getIncludedLayout());
1038510dab6a17ccd59a2a9cbc07f900dfc2f11ff2bGeorge Mount                            if (target.getId() == null) {
1048510dab6a17ccd59a2a9cbc07f900dfc2f11ff2bGeorge Mount                                unboundIncludes.add(target);
1058510dab6a17ccd59a2a9cbc07f900dfc2f11ff2bGeorge Mount                            } else {
1068510dab6a17ccd59a2a9cbc07f900dfc2f11ff2bGeorge Mount                                target.setIncludedLayout(null);
1078510dab6a17ccd59a2a9cbc07f900dfc2f11ff2bGeorge Mount                                target.setInterfaceType("android.view.View");
1088510dab6a17ccd59a2a9cbc07f900dfc2f11ff2bGeorge Mount                                target.mViewName = "android.view.View";
1098510dab6a17ccd59a2a9cbc07f900dfc2f11ff2bGeorge Mount                            }
1107ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                        } else {
1117ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                            String binding = boundTo.get(0).getFullBindingClass();
1127ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                            target.setInterfaceType(binding);
1137ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                        }
1147ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                    }
1157ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                }
1168510dab6a17ccd59a2a9cbc07f900dfc2f11ff2bGeorge Mount                layoutFileBundle.getBindingTargetBundles().removeAll(unboundIncludes);
1177ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            }
1187ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        }
1197ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount
1200c2ed0cbaee2f206e926bfc780b05e9f1e52b551Yigit Boyar        for (Map.Entry<String, List<LayoutFileBundle>> bundles : mLayoutBundles.entrySet()) {
1210c2ed0cbaee2f206e926bfc780b05e9f1e52b551Yigit Boyar            if (bundles.getValue().size() < 2) {
1220c2ed0cbaee2f206e926bfc780b05e9f1e52b551Yigit Boyar                continue;
1230c2ed0cbaee2f206e926bfc780b05e9f1e52b551Yigit Boyar            }
124aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar
1253bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            // validate all ids are in correct view types
1263bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            // and all variables have the same name
1273bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            for (LayoutFileBundle bundle : bundles.getValue()) {
1283bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                bundle.mHasVariations = true;
1293bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            }
130aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            String bindingClass = validateAndGetSharedClassName(bundles.getValue());
131aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            Map<String, NameTypeLocation> variableTypes = validateAndMergeNameTypeLocations(
132aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    bundles.getValue(), ErrorMessages.MULTI_CONFIG_VARIABLE_TYPE_MISMATCH,
133aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    new ValidateAndFilterCallback() {
134aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                        @Override
13523910cf498c35704a03ba4f3889de2ab97ccbe21George Mount                        public List<? extends NameTypeLocation> get(LayoutFileBundle bundle) {
136aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                            return bundle.mVariables;
137aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                        }
138aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    });
139aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar
140aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            Map<String, NameTypeLocation> importTypes = validateAndMergeNameTypeLocations(
141aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    bundles.getValue(), ErrorMessages.MULTI_CONFIG_IMPORT_TYPE_MISMATCH,
142aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    new ValidateAndFilterCallback() {
143aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                        @Override
144aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                        public List<NameTypeLocation> get(LayoutFileBundle bundle) {
145aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                            return bundle.mImports;
146aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                        }
147aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    });
1483bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
1493bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            for (LayoutFileBundle bundle : bundles.getValue()) {
1503bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                // now add missing ones to each to ensure they can be referenced
1513bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                L.d("checking for missing variables in %s / %s", bundle.mFileName,
1523bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                        bundle.mConfigName);
153c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                for (Map.Entry<String, NameTypeLocation> variable : variableTypes.entrySet()) {
154c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    if (!NameTypeLocation.contains(bundle.mVariables, variable.getKey())) {
15523910cf498c35704a03ba4f3889de2ab97ccbe21George Mount                        NameTypeLocation orig = variable.getValue();
15623910cf498c35704a03ba4f3889de2ab97ccbe21George Mount                        bundle.addVariable(orig.name, orig.type, orig.location, false);
1573bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                        L.d("adding missing variable %s to %s / %s", variable.getKey(),
1583bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                                bundle.mFileName, bundle.mConfigName);
1593bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                    }
1603bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                }
161c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                for (Map.Entry<String, NameTypeLocation> userImport : importTypes.entrySet()) {
162c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    if (!NameTypeLocation.contains(bundle.mImports, userImport.getKey())) {
163c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                        bundle.mImports.add(userImport.getValue());
1643bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                        L.d("adding missing import %s to %s / %s", userImport.getKey(),
1653bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                                bundle.mFileName, bundle.mConfigName);
1663bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                    }
1673bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                }
1683bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            }
1693bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
170895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            Set<String> includeBindingIds = new HashSet<String>();
171895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            Set<String> viewBindingIds = new HashSet<String>();
172895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar            Map<String, String> viewTypes = new HashMap<String, String>();
17334a18e6a231f3b64726bd93e7e097a0d5a75995dGeorge Mount            Map<String, String> includes = new HashMap<String, String>();
1743bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            L.d("validating ids for %s", bundles.getKey());
1759784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar            Set<String> conflictingIds = new HashSet<String>();
1763bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            for (LayoutFileBundle bundle : bundles.getValue()) {
177aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                try {
178aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    Scope.enter(bundle);
179aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    for (BindingTargetBundle target : bundle.mBindingTargetBundles) {
180aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                        try {
181aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                            Scope.enter(target);
182aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                            L.d("checking %s %s %s", target.getId(), target.getFullClassName(),
183aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                    target.isBinder());
184aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                            if (target.mId != null) {
185aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                if (target.isBinder()) {
186aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                    if (viewBindingIds.contains(target.mId)) {
187aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                        L.d("%s is conflicting", target.mId);
188aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                        conflictingIds.add(target.mId);
189aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                        continue;
190aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                    }
191aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                    includeBindingIds.add(target.mId);
192aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                } else {
193aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                    if (includeBindingIds.contains(target.mId)) {
194aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                        L.d("%s is conflicting", target.mId);
195aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                        conflictingIds.add(target.mId);
196aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                        continue;
197aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                    }
198aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                    viewBindingIds.add(target.mId);
199aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                }
200aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                String existingType = viewTypes.get(target.mId);
201aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                if (existingType == null) {
202aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                    L.d("assigning %s as %s", target.getId(),
203aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                            target.getFullClassName());
204aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                            viewTypes.put(target.mId, target.getFullClassName());
205aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                    if (target.isBinder()) {
206aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                        includes.put(target.mId, target.getIncludedLayout());
207aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                    }
208aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                } else if (!existingType.equals(target.getFullClassName())) {
209aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                    if (target.isBinder()) {
210aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                        L.d("overriding %s as base binder", target.getId());
211aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                        viewTypes.put(target.mId,
212aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                                "android.databinding.ViewDataBinding");
213aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                        includes.put(target.mId, target.getIncludedLayout());
214aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                    } else {
215aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                        L.d("overriding %s as base view", target.getId());
216aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                        viewTypes.put(target.mId, "android.view.View");
217aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                    }
218aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                }
2190c2ed0cbaee2f206e926bfc780b05e9f1e52b551Yigit Boyar                            }
220aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                        } catch (ScopedException ex) {
221aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                            Scope.defer(ex);
222aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                        } finally {
223aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                            Scope.exit();
22496e1c821dd446d1ed78f8ae61131550588f60a24George Mount                        }
225aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    }
226aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                } finally {
227aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    Scope.exit();
228aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                }
229aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            }
230aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar
231aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            if (!conflictingIds.isEmpty()) {
232aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                for (LayoutFileBundle bundle : bundles.getValue()) {
233aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    for (BindingTargetBundle target : bundle.mBindingTargetBundles) {
234aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                        if (conflictingIds.contains(target.mId)) {
235aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                            Scope.registerError(String.format(
236aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                            ErrorMessages.MULTI_CONFIG_ID_USED_AS_IMPORT,
237aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                            target.mId), bundle, target);
2383bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                        }
2393bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                    }
2403bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                }
2413bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            }
2423bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
2433bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            for (LayoutFileBundle bundle : bundles.getValue()) {
244aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                try {
245aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    Scope.enter(bundle);
246aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    for (Map.Entry<String, String> viewType : viewTypes.entrySet()) {
247aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                        BindingTargetBundle target = bundle.getBindingTargetById(viewType.getKey());
248aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                        if (target == null) {
249aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                            String include = includes.get(viewType.getKey());
250aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                            if (include == null) {
251aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                bundle.createBindingTarget(viewType.getKey(), viewType.getValue(),
252aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                        false, null, null, null);
253aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                            } else {
254aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                BindingTargetBundle bindingTargetBundle = bundle
255aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                        .createBindingTarget(
256aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                                viewType.getKey(), null, false, null, null, null);
257aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                bindingTargetBundle
258aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                        .setIncludedLayout(includes.get(viewType.getKey()));
259aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                bindingTargetBundle.setInterfaceType(viewType.getValue());
260aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                            }
2617ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                        } else {
262aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                            L.d("setting interface type on %s (%s) as %s", target.mId,
263aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                    target.getFullClassName(), viewType.getValue());
264aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                            target.setInterfaceType(viewType.getValue());
2657ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                        }
2663bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                    }
267aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                } catch (ScopedException ex) {
268aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    Scope.defer(ex);
269aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                } finally {
270aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    Scope.exit();
2713bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                }
2723bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            }
2733bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
2743bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        // assign class names to each
2753bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        for (Map.Entry<String, List<LayoutFileBundle>> entry : mLayoutBundles.entrySet()) {
2763bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            for (LayoutFileBundle bundle : entry.getValue()) {
2773bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                final String configName;
2783bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                if (bundle.hasVariations()) {
2793bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                    // append configuration specifiers.
2808e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount                    final String parentFileName = bundle.mDirectory;
2818e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount                    L.d("parent file for %s is %s", bundle.getFileName(), parentFileName);
2823bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                    if ("layout".equals(parentFileName)) {
2833bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                        configName = "";
2843bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                    } else {
2850cb9fbb96197af013f4f879ed6cddf2681b88fd6Yigit Boyar                        configName = ParserHelper.toClassName(parentFileName.substring("layout-".length()));
2863bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                    }
2873bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                } else {
2883bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                    configName = "";
2893bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                }
2903bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                bundle.mConfigName = configName;
2913bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            }
2923bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
2933bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar    }
2943bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
295aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar    /**
296aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar     * Receives a list of bundles which are representations of the same layout file in different
297aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar     * configurations.
298aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar     * @param bundles
299aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar     * @return The map for variables and their types
300aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar     */
301aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar    private Map<String, NameTypeLocation> validateAndMergeNameTypeLocations(
302aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            List<LayoutFileBundle> bundles, String errorMessage,
303aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            ValidateAndFilterCallback callback) {
3049784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar        Map<String, NameTypeLocation> result = new HashMap<String, NameTypeLocation>();
3059784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar        Set<String> mismatched = new HashSet<String>();
306aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        for (LayoutFileBundle bundle : bundles) {
307aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            for (NameTypeLocation item : callback.get(bundle)) {
308aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                NameTypeLocation existing = result.get(item.name);
309aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                if (existing != null && !existing.type.equals(item.type)) {
310aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    mismatched.add(item.name);
311aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    continue;
312aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                }
313aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                result.put(item.name, item);
314aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            }
315aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        }
316aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        if (mismatched.isEmpty()) {
317aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            return result;
318aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        }
319aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        // create exceptions. We could get more clever and find the outlier but for now, listing
320aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        // each file w/ locations seems enough
321aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        for (String mismatch : mismatched) {
322aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            for (LayoutFileBundle bundle : bundles) {
323aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                NameTypeLocation found = null;
324aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                for (NameTypeLocation item : callback.get(bundle)) {
325aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    if (mismatch.equals(item.name)) {
326aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                        found = item;
327aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                        break;
328aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    }
329aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                }
330aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                if (found == null) {
331aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    // variable is not defined in this layout, continue
332aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    continue;
333aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                }
334aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                Scope.registerError(String.format(
335aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                errorMessage, found.name, found.type,
336aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                                bundle.mDirectory + "/" + bundle.getFileName()), bundle,
337aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                        found.location.createScope());
338aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            }
339aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        }
340aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        return result;
341aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar    }
342aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar
343aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar    /**
344aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar     * Receives a list of bundles which are representations of the same layout file in different
345aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar     * configurations.
346aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar     * @param bundles
347aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar     * @return The shared class name for these bundles
348aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar     */
349aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar    private String validateAndGetSharedClassName(List<LayoutFileBundle> bundles) {
350aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        String sharedClassName = null;
351aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        boolean hasMismatch = false;
352aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        for (LayoutFileBundle bundle : bundles) {
353aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            bundle.mHasVariations = true;
354aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            String fullBindingClass = bundle.getFullBindingClass();
355aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            if (sharedClassName == null) {
356aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                sharedClassName = fullBindingClass;
357aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            } else if (!sharedClassName.equals(fullBindingClass)) {
358aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                hasMismatch = true;
359aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                break;
360aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            }
361aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        }
362aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        if (!hasMismatch) {
363aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            return sharedClassName;
364aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        }
365aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        // generate proper exceptions for each
366aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        for (LayoutFileBundle bundle : bundles) {
367aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            Scope.registerError(String.format(ErrorMessages.MULTI_CONFIG_LAYOUT_CLASS_NAME_MISMATCH,
368aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    bundle.getFullBindingClass(), bundle.mDirectory + "/" + bundle.getFileName()),
369aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    bundle, bundle.getClassNameLocationProvider());
370aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        }
371aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        return sharedClassName;
372aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar    }
373aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar
3749784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar    public void addRemovedFile(File file) {
3759784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar        mRemovedFiles.add(file);
3769784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar    }
3779784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar
3789784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar    public List<File> getRemovedFiles() {
3799784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar        return mRemovedFiles;
3809784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar    }
3819784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar
3828e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount    @XmlAccessorType(XmlAccessType.NONE)
3838e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount    @XmlRootElement(name="Layout")
384aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar    public static class LayoutFileBundle implements Serializable, FileScopeProvider {
3858e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        @XmlAttribute(name="layout", required = true)
3868e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        public String mFileName;
387a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        @XmlAttribute(name="modulePackage", required = true)
388a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        public String mModulePackage;
389731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        @XmlAttribute(name="absoluteFilePath", required = true)
390731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        public String mAbsoluteFilePath;
3913bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        private String mConfigName;
3923bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
3937ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        // The binding class as given by the user
3947ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        @XmlAttribute(name="bindingClass", required = false)
3957ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        public String mBindingClass;
3967ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount
397aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        // The location of the name of the generated class, optional
398aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        @XmlElement(name = "ClassNameLocation", required = false)
399aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        private Location mClassNameLocation;
4007ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        // The full package and class name as determined from mBindingClass and mModulePackage
4017ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        private String mFullBindingClass;
4027ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount
4037ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        // The simple binding class name as determined from mBindingClass and mModulePackage
4047ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        private String mBindingClassName;
4057ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount
4067ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        // The package of the binding class as determined from mBindingClass and mModulePackage
4077ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        private String mBindingPackage;
4087ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount
4098e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        @XmlAttribute(name="directory", required = true)
4108e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        public String mDirectory;
4118e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        public boolean mHasVariations;
4128e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount
4138e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        @XmlElement(name="Variables")
4149784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar        public List<VariableDeclaration> mVariables = new ArrayList<VariableDeclaration>();
4153bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
4168e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        @XmlElement(name="Imports")
4179784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar        public List<NameTypeLocation> mImports = new ArrayList<NameTypeLocation>();
4183bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
4198e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        @XmlElementWrapper(name="Targets")
4208e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        @XmlElement(name="Target")
421895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        public List<BindingTargetBundle> mBindingTargetBundles = new ArrayList<BindingTargetBundle>();
4228e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount
42396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        @XmlAttribute(name="isMerge", required = true)
42496e1c821dd446d1ed78f8ae61131550588f60a24George Mount        private boolean mIsMerge;
42596e1c821dd446d1ed78f8ae61131550588f60a24George Mount
426aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        private LocationScopeProvider mClassNameLocationProvider;
427aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar
4288e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        // for XML binding
4298e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        public LayoutFileBundle() {
4308e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        }
4318e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount
43228e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar        /**
43328e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar         * Updates configuration fields from the given bundle but does not change variables,
43428e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar         * binding expressions etc.
43528e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar         */
43628e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar        public void inheritConfigurationFrom(LayoutFileBundle other) {
43728e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar            mFileName = other.mFileName;
43828e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar            mModulePackage = other.mModulePackage;
43928e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar            mBindingClass = other.mBindingClass;
44028e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar            mFullBindingClass = other.mFullBindingClass;
44128e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar            mBindingClassName = other.mBindingClassName;
44228e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar            mBindingPackage = other.mBindingPackage;
44328e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar            mHasVariations = other.mHasVariations;
44428e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar            mIsMerge = other.mIsMerge;
44528e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar        }
44628e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar
447731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        public LayoutFileBundle(File file, String fileName, String directory,
448731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                String modulePackage, boolean isMerge) {
4493bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            mFileName = fileName;
4508e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount            mDirectory = directory;
451a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            mModulePackage = modulePackage;
45296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            mIsMerge = isMerge;
453731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            mAbsoluteFilePath = file.getAbsolutePath();
4543bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
4553bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
456aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        public LocationScopeProvider getClassNameLocationProvider() {
457aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            if (mClassNameLocationProvider == null && mClassNameLocation != null
458aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                    && mClassNameLocation.isValid()) {
459aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar                mClassNameLocationProvider = mClassNameLocation.createScope();
460aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            }
461aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            return mClassNameLocationProvider;
462aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        }
463aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar
46423910cf498c35704a03ba4f3889de2ab97ccbe21George Mount        public void addVariable(String name, String type, Location location, boolean declared) {
465c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            Preconditions.check(!NameTypeLocation.contains(mVariables, name),
466c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    "Cannot use same variable name twice. %s in %s", name, location);
46723910cf498c35704a03ba4f3889de2ab97ccbe21George Mount            mVariables.add(new VariableDeclaration(name, type, location, declared));
4683bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
4693bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
470c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        public void addImport(String alias, String type, Location location) {
471c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            Preconditions.check(!NameTypeLocation.contains(mImports, alias),
472c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    "Cannot import same alias twice. %s in %s", alias, location);
473c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            mImports.add(new NameTypeLocation(alias, type, location));
4743bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
4753bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
4767ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        public BindingTargetBundle createBindingTarget(String id, String viewName,
477c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                boolean used, String tag, String originalTag, Location location) {
4787ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            BindingTargetBundle target = new BindingTargetBundle(id, viewName, used, tag,
479c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    originalTag, location);
4803bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            mBindingTargetBundles.add(target);
4813bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            return target;
4823bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
4833bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
4843bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        public boolean isEmpty() {
4853bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            return mVariables.isEmpty() && mImports.isEmpty() && mBindingTargetBundles.isEmpty();
4863bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
4873bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
4883bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        public BindingTargetBundle getBindingTargetById(String key) {
4893bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            for (BindingTargetBundle target : mBindingTargetBundles) {
4903bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                if (key.equals(target.mId)) {
4913bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                    return target;
4923bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                }
4933bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            }
4943bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            return null;
4953bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
4963bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
4973bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        public String getFileName() {
4983bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            return mFileName;
4993bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
5003bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
5013bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        public String getConfigName() {
5023bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            return mConfigName;
5033bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
5043bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
5058e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        public String getDirectory() {
5068e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount            return mDirectory;
5078e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        }
5088e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount
5093bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        public boolean hasVariations() {
5103bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            return mHasVariations;
5113bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
5123bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
51323910cf498c35704a03ba4f3889de2ab97ccbe21George Mount        public List<VariableDeclaration> getVariables() {
5143bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            return mVariables;
5153bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
5163bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
517c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        public List<NameTypeLocation> getImports() {
5183bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            return mImports;
5193bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
5203bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
52196e1c821dd446d1ed78f8ae61131550588f60a24George Mount        public boolean isMerge() {
52296e1c821dd446d1ed78f8ae61131550588f60a24George Mount            return mIsMerge;
52396e1c821dd446d1ed78f8ae61131550588f60a24George Mount        }
52496e1c821dd446d1ed78f8ae61131550588f60a24George Mount
5257ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        public String getBindingClassName() {
5267ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            if (mBindingClassName == null) {
5277ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                String fullClass = getFullBindingClass();
5287ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                int dotIndex = fullClass.lastIndexOf('.');
5297ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                mBindingClassName = fullClass.substring(dotIndex + 1);
5307ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            }
5317ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            return mBindingClassName;
5327ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        }
5337ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount
534aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        public void setBindingClass(String bindingClass, Location location) {
5353b8fedce6e9ee814ffe7b63d07aa5456f08fb9b2George Mount            mBindingClass = bindingClass;
536aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            mClassNameLocation = location;
5373b8fedce6e9ee814ffe7b63d07aa5456f08fb9b2George Mount        }
5383b8fedce6e9ee814ffe7b63d07aa5456f08fb9b2George Mount
5397ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        public String getBindingClassPackage() {
5407ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            if (mBindingPackage == null) {
5417ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                String fullClass = getFullBindingClass();
5427ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                int dotIndex = fullClass.lastIndexOf('.');
5437ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                mBindingPackage = fullClass.substring(0, dotIndex);
5447ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            }
5457ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            return mBindingPackage;
5467ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        }
5477ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount
5487ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        private String getFullBindingClass() {
5497ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            if (mFullBindingClass == null) {
5507ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                if (mBindingClass == null) {
5517ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                    mFullBindingClass = getModulePackage() + ".databinding." +
5520cb9fbb96197af013f4f879ed6cddf2681b88fd6Yigit Boyar                            ParserHelper.toClassName(getFileName()) + "Binding";
5537ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                } else if (mBindingClass.startsWith(".")) {
5547ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                    mFullBindingClass = getModulePackage() + mBindingClass;
5557ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                } else if (mBindingClass.indexOf('.') < 0) {
5567ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                    mFullBindingClass = getModulePackage() + ".databinding." + mBindingClass;
5577ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                } else {
5587ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                    mFullBindingClass = mBindingClass;
5597ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                }
5607ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            }
5617ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            return mFullBindingClass;
5627ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        }
5637ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount
5643bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        public List<BindingTargetBundle> getBindingTargetBundles() {
5653bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            return mBindingTargetBundles;
5663bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
567a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar
568a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        @Override
569a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        public boolean equals(Object o) {
570a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            if (this == o) {
571a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                return true;
572a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            }
573a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            if (o == null || getClass() != o.getClass()) {
574a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                return false;
575a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            }
576a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar
577a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            LayoutFileBundle bundle = (LayoutFileBundle) o;
578a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar
579a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            if (mConfigName != null ? !mConfigName.equals(bundle.mConfigName)
580a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                    : bundle.mConfigName != null) {
581a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                return false;
582a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            }
583a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            if (mDirectory != null ? !mDirectory.equals(bundle.mDirectory)
584a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                    : bundle.mDirectory != null) {
585a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                return false;
586a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            }
587af146d6a8c0efcf5682d14047c06866a5548f78fYigit Boyar            return !(mFileName != null ? !mFileName.equals(bundle.mFileName)
588af146d6a8c0efcf5682d14047c06866a5548f78fYigit Boyar                    : bundle.mFileName != null);
589a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar
590a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        }
591a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar
592a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        @Override
593a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        public int hashCode() {
594a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            int result = mFileName != null ? mFileName.hashCode() : 0;
595a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            result = 31 * result + (mConfigName != null ? mConfigName.hashCode() : 0);
596a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            result = 31 * result + (mDirectory != null ? mDirectory.hashCode() : 0);
597a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            return result;
598a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        }
599a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar
600a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        @Override
601a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        public String toString() {
602a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            return "LayoutFileBundle{" +
603a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                    "mHasVariations=" + mHasVariations +
604a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                    ", mDirectory='" + mDirectory + '\'' +
605a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                    ", mConfigName='" + mConfigName + '\'' +
606a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                    ", mModulePackage='" + mModulePackage + '\'' +
607a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                    ", mFileName='" + mFileName + '\'' +
608a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar                    '}';
609a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        }
610a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar
611a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        public String getModulePackage() {
612a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar            return mModulePackage;
613a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar        }
614731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
615731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        public String getAbsoluteFilePath() {
616731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return mAbsoluteFilePath;
617731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
618aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar
619aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        @Override
620aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        public String provideScopeFilePath() {
621aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar            return mAbsoluteFilePath;
622aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar        }
62328e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar
62428e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar        private static Marshaller sMarshaller;
62528e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar        private static Unmarshaller sUmarshaller;
62628e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar
62728e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar        public String toXML() throws JAXBException {
62828e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar            StringWriter writer = new StringWriter();
62928e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar            getMarshaller().marshal(this, writer);
63028e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar            return writer.getBuffer().toString();
63128e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar        }
63228e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar
63328e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar        public static LayoutFileBundle fromXML(InputStream inputStream) throws JAXBException {
63428e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar            return (LayoutFileBundle) getUnmarshaller().unmarshal(inputStream);
63528e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar        }
63628e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar
63728e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar        private static Marshaller getMarshaller() throws JAXBException {
63828e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar            if (sMarshaller == null) {
63928e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar                JAXBContext context = JAXBContext
64028e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar                        .newInstance(ResourceBundle.LayoutFileBundle.class);
64128e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar                sMarshaller = context.createMarshaller();
64228e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar            }
64328e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar            return sMarshaller;
64428e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar        }
64528e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar
64628e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar        private static Unmarshaller getUnmarshaller() throws JAXBException {
64728e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar            if (sUmarshaller == null) {
64828e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar                JAXBContext context = JAXBContext
64928e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar                        .newInstance(ResourceBundle.LayoutFileBundle.class);
65028e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar                sUmarshaller = context.createUnmarshaller();
65128e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar            }
65228e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar            return sUmarshaller;
65328e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar        }
6543bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar    }
6553bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
6568e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount    @XmlAccessorType(XmlAccessType.NONE)
657c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar    public static class NameTypeLocation {
6588e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        @XmlAttribute(name="type", required = true)
6598e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        public String type;
6608e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount
6618e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        @XmlAttribute(name="name", required = true)
6628e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        public String name;
663c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
664c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        @XmlElement(name="location", required = false)
665c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        public Location location;
666c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
667c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        public NameTypeLocation() {
668c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
669c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
670c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        public NameTypeLocation(String name, String type, Location location) {
671c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            this.type = type;
672c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            this.name = name;
673c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            this.location = location;
674c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
675c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
676c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        @Override
677c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        public String toString() {
678c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return "{" +
679c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    "type='" + type + '\'' +
680c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    ", name='" + name + '\'' +
681c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    ", location=" + location +
682c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    '}';
683c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
684c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
685c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        @Override
686c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        public boolean equals(Object o) {
687c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            if (this == o) {
688c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                return true;
689c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            }
690c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            if (o == null || getClass() != o.getClass()) {
691c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                return false;
692c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            }
693c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
694c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            NameTypeLocation that = (NameTypeLocation) o;
695c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
696c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            if (location != null ? !location.equals(that.location) : that.location != null) {
697c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                return false;
698c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            }
699c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            if (!name.equals(that.name)) {
700c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                return false;
701c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            }
702af146d6a8c0efcf5682d14047c06866a5548f78fYigit Boyar            return type.equals(that.type);
703c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
704c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
705c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
706c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        @Override
707c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        public int hashCode() {
708c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            int result = type.hashCode();
709c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            result = 31 * result + name.hashCode();
710c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            result = 31 * result + (location != null ? location.hashCode() : 0);
711c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return result;
712c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
713c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
71423910cf498c35704a03ba4f3889de2ab97ccbe21George Mount        public static boolean contains(List<? extends NameTypeLocation> list, String name) {
715c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            for (NameTypeLocation ntl : list) {
716c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                if (name.equals(ntl.name)) {
717c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                    return true;
718c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                }
719c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            }
720c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return false;
721c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
7228e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount    }
7238e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount
72423910cf498c35704a03ba4f3889de2ab97ccbe21George Mount    @XmlAccessorType(XmlAccessType.NONE)
72523910cf498c35704a03ba4f3889de2ab97ccbe21George Mount    public static class VariableDeclaration extends NameTypeLocation {
72623910cf498c35704a03ba4f3889de2ab97ccbe21George Mount        @XmlAttribute(name="declared", required = false)
72723910cf498c35704a03ba4f3889de2ab97ccbe21George Mount        public boolean declared;
72823910cf498c35704a03ba4f3889de2ab97ccbe21George Mount
72923910cf498c35704a03ba4f3889de2ab97ccbe21George Mount        public VariableDeclaration() {
73023910cf498c35704a03ba4f3889de2ab97ccbe21George Mount
73123910cf498c35704a03ba4f3889de2ab97ccbe21George Mount        }
73223910cf498c35704a03ba4f3889de2ab97ccbe21George Mount
73323910cf498c35704a03ba4f3889de2ab97ccbe21George Mount        public VariableDeclaration(String name, String type, Location location, boolean declared) {
73423910cf498c35704a03ba4f3889de2ab97ccbe21George Mount            super(name, type, location);
73523910cf498c35704a03ba4f3889de2ab97ccbe21George Mount            this.declared = declared;
73623910cf498c35704a03ba4f3889de2ab97ccbe21George Mount        }
73723910cf498c35704a03ba4f3889de2ab97ccbe21George Mount    }
73823910cf498c35704a03ba4f3889de2ab97ccbe21George Mount
7398e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount    public static class MarshalledMapType {
740c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        public List<NameTypeLocation> entries;
7418e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount    }
7423bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
7438e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount    @XmlAccessorType(XmlAccessType.NONE)
744731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar    public static class BindingTargetBundle implements Serializable, LocationScopeProvider {
7458e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        // public for XML serialization
7468e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount
7478e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        @XmlAttribute(name="id")
7488e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        public String mId;
7498e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        @XmlAttribute(name="tag", required = true)
7508e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        public String mTag;
7518e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        @XmlAttribute(name="originalTag")
7528e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        public String mOriginalTag;
7537ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        @XmlAttribute(name="view", required = false)
7547ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        public String mViewName;
7557ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        private String mFullClassName;
7568e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        public boolean mUsed = true;
7578e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        @XmlElementWrapper(name="Expressions")
7588e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        @XmlElement(name="Expression")
759895b618d9c6e3deb56465d0759cda57f50c46214Yigit Boyar        public List<BindingBundle> mBindingBundleList = new ArrayList<BindingBundle>();
7608e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        @XmlAttribute(name="include")
7618e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        public String mIncludedLayout;
762c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        @XmlElement(name="location")
763c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        public Location mLocation;
7643bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        private String mInterfaceType;
7653bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
7668e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        // For XML serialization
7678e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        public BindingTargetBundle() {}
7688e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount
7697ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount        public BindingTargetBundle(String id, String viewName, boolean used,
770c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar                String tag, String originalTag, Location location) {
7713bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            mId = id;
7727ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            mViewName = viewName;
7733bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            mUsed = used;
7748e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount            mTag = tag;
7758e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount            mOriginalTag = originalTag;
776c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            mLocation = location;
7773bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
7783bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
779d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount        public void addBinding(String name, String expr, boolean isTwoWay, Location location,
780d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                Location valueLocation) {
781d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            mBindingBundleList.add(new BindingBundle(name, expr, isTwoWay, location, valueLocation));
7823bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
7833bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
7843bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        public void setIncludedLayout(String includedLayout) {
7853bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            mIncludedLayout = includedLayout;
7863bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
7873bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
7883bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        public String getIncludedLayout() {
7893bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            return mIncludedLayout;
7903bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
7913bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
7923bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        public boolean isBinder() {
7933bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            return mIncludedLayout != null;
7943bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
7953bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
7963bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        public void setInterfaceType(String interfaceType) {
7973bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            mInterfaceType = interfaceType;
7983bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
7993bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
800c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        public void setLocation(Location location) {
801c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            mLocation = location;
802c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
803c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
804c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        public Location getLocation() {
805c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar            return mLocation;
806c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar        }
807c1560e6b00b398867da12fbdc5a1fcd1d50b801cYigit Boyar
8083bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        public String getId() {
8093bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            return mId;
8103bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
8113bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
81200da715547ee7d5d38a3b8576090ca427a94daa5George Mount        public String getTag() {
81300da715547ee7d5d38a3b8576090ca427a94daa5George Mount            return mTag;
81400da715547ee7d5d38a3b8576090ca427a94daa5George Mount        }
81500da715547ee7d5d38a3b8576090ca427a94daa5George Mount
81600da715547ee7d5d38a3b8576090ca427a94daa5George Mount        public String getOriginalTag() {
81700da715547ee7d5d38a3b8576090ca427a94daa5George Mount            return mOriginalTag;
81800da715547ee7d5d38a3b8576090ca427a94daa5George Mount        }
81900da715547ee7d5d38a3b8576090ca427a94daa5George Mount
8203bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        public String getFullClassName() {
8217ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            if (mFullClassName == null) {
8227ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                if (isBinder()) {
8237ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                    mFullClassName = mInterfaceType;
8247ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                } else if (mViewName.indexOf('.') == -1) {
8254ba16229a40e9758db86d4fb1df5119fdcb8aa2aDeepanshu Gupta                    if (Arrays.asList(ANDROID_VIEW_PACKAGE_VIEWS).contains(mViewName)) {
8267ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                        mFullClassName = "android.view." + mViewName;
827a97508c49c11bbc92722192890ca43a3bf6d3036Yigit Boyar                    } else if("WebView".equals(mViewName)) {
828a97508c49c11bbc92722192890ca43a3bf6d3036Yigit Boyar                        mFullClassName = "android.webkit." + mViewName;
8297ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                    } else {
8307ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                        mFullClassName = "android.widget." + mViewName;
8317ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                    }
8327ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                } else {
8337ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                    mFullClassName = mViewName;
8347ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                }
8357ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            }
8367ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            if (mFullClassName == null) {
8377ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                L.e("Unexpected full class name = null. view = %s, interface = %s, layout = %s",
8387ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount                        mViewName, mInterfaceType, mIncludedLayout);
8397ff60c24c6de7ba0c674fe65a82ad4a88dab2e5dGeorge Mount            }
8403bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            return mFullClassName;
8413bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
8423bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
8433bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        public boolean isUsed() {
8443bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            return mUsed;
8453bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
8463bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
8473bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        public List<BindingBundle> getBindingBundleList() {
8483bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            return mBindingBundleList;
8493bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
8503bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
8513bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        public String getInterfaceType() {
8523bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            return mInterfaceType;
8533bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
8543bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
855731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        @Override
856731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        public List<Location> provideScopeLocation() {
857731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            return mLocation == null ? null : Arrays.asList(mLocation);
858731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar        }
859731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
8608e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount        @XmlAccessorType(XmlAccessType.NONE)
861b134dd773c386246ee8b692fbc4f063945e88ec5Yigit Boyar        public static class BindingBundle implements Serializable {
8623bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
8633bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            private String mName;
8643bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            private String mExpr;
865731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            private Location mLocation;
866731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            private Location mValueLocation;
867d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            private boolean mIsTwoWay;
8683bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
8698e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount            public BindingBundle() {}
8708e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount
871d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            public BindingBundle(String name, String expr, boolean isTwoWay, Location location,
872731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                    Location valueLocation) {
8733bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                mName = name;
8743bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                mExpr = expr;
875731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                mLocation = location;
876d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                mIsTwoWay = isTwoWay;
877731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                mValueLocation = valueLocation;
8783bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            }
8793bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
8808e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount            @XmlAttribute(name="attribute", required=true)
8813bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            public String getName() {
8823bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                return mName;
8833bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            }
8843bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar
8858e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount            @XmlAttribute(name="text", required=true)
8863bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            public String getExpr() {
8873bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar                return mExpr;
8883bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar            }
8898e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount
8908e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount            public void setName(String name) {
8918e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount                mName = name;
8928e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount            }
8938e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount
8948e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount            public void setExpr(String expr) {
8958e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount                mExpr = expr;
8968e5d3b4aa4e47fc0150b4a26b58ec6e5c17b9d16George Mount            }
897731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
898d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            public void setTwoWay(boolean isTwoWay) {
899d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                mIsTwoWay = isTwoWay;
900d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            }
901d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount
902731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            @XmlElement(name="Location")
903731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            public Location getLocation() {
904731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                return mLocation;
905731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            }
906731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
907731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            public void setLocation(Location location) {
908731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                mLocation = location;
909731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            }
910731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
911731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            @XmlElement(name="ValueLocation")
912731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            public Location getValueLocation() {
913731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                return mValueLocation;
914731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            }
915731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar
916d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            @XmlElement(name="TwoWay")
917d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            public boolean isTwoWay() {
918d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount                return mIsTwoWay;
919d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount            }
920d3f2b9229472c9dae9bf4ae8b3e2d653b5653b01George Mount
921731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            public void setValueLocation(Location valueLocation) {
922731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar                mValueLocation = valueLocation;
923731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar            }
9243bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar        }
9253bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar    }
926aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar
927aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar    /**
928aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar     * Just an inner callback class to process imports and variables w/ the same code.
929aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar     */
930aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar    private interface ValidateAndFilterCallback {
93123910cf498c35704a03ba4f3889de2ab97ccbe21George Mount        List<? extends NameTypeLocation> get(LayoutFileBundle bundle);
932aafbe5a2394ff9826201cca97d3298a9f355e311Yigit Boyar    }
9333bd87eef217d80a233677d7e267224d0ed3c2c55Yigit Boyar}
934