1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.layoutlib.bridge.intensive.setup;
18
19import com.android.ide.common.rendering.api.ILayoutPullParser;
20
21import org.kxml2.io.KXmlParser;
22import org.xmlpull.v1.XmlPullParserException;
23
24import android.annotation.NonNull;
25
26import java.io.ByteArrayInputStream;
27import java.io.File;
28import java.io.FileInputStream;
29import java.io.FileNotFoundException;
30import java.io.IOError;
31import java.io.InputStream;
32import java.nio.charset.Charset;
33import java.util.HashMap;
34import java.util.Map;
35
36import static com.android.SdkConstants.ATTR_IGNORE;
37import static com.android.SdkConstants.EXPANDABLE_LIST_VIEW;
38import static com.android.SdkConstants.GRID_VIEW;
39import static com.android.SdkConstants.LIST_VIEW;
40import static com.android.SdkConstants.SPINNER;
41import static com.android.SdkConstants.TOOLS_URI;
42
43public class LayoutPullParser extends KXmlParser implements ILayoutPullParser{
44    @NonNull
45    public static LayoutPullParser createFromFile(@NonNull File layoutFile)
46            throws FileNotFoundException {
47        return new LayoutPullParser(new FileInputStream(layoutFile));
48    }
49
50    /**
51     * @param layoutPath Must start with '/' and be relative to test resources.
52     */
53    @NonNull
54    public static LayoutPullParser createFromPath(@NonNull String layoutPath) {
55        if (layoutPath.startsWith("/")) {
56            layoutPath = layoutPath.substring(1);
57        }
58
59        return new LayoutPullParser(LayoutPullParser.class.getClassLoader().getResourceAsStream
60                (layoutPath));
61    }
62
63    @NonNull
64    public static LayoutPullParser createFromString(@NonNull String contents) {
65        return new LayoutPullParser(new ByteArrayInputStream(
66                contents.getBytes(Charset.forName("UTF-8"))));
67    }
68
69    private LayoutPullParser(@NonNull InputStream inputStream) {
70        try {
71            setFeature(FEATURE_PROCESS_NAMESPACES, true);
72            setInput(inputStream, null);
73        } catch (XmlPullParserException e) {
74            throw new IOError(e);
75        }
76    }
77
78    @Override
79    public Object getViewCookie() {
80        // TODO: Implement this properly.
81        String name = super.getName();
82        if (name == null) {
83            return null;
84        }
85
86        // Store tools attributes if this looks like a layout we'll need adapter view
87        // bindings for in the LayoutlibCallback.
88        if (LIST_VIEW.equals(name) || EXPANDABLE_LIST_VIEW.equals(name) || GRID_VIEW.equals(name) || SPINNER.equals(name)) {
89            Map<String, String> map = null;
90            int count = getAttributeCount();
91            for (int i = 0; i < count; i++) {
92                String namespace = getAttributeNamespace(i);
93                if (namespace != null && namespace.equals(TOOLS_URI)) {
94                    String attribute = getAttributeName(i);
95                    if (attribute.equals(ATTR_IGNORE)) {
96                        continue;
97                    }
98                    if (map == null) {
99                        map = new HashMap<String, String>(4);
100                    }
101                    map.put(attribute, getAttributeValue(i));
102                }
103            }
104
105            return map;
106        }
107
108        return null;
109    }
110
111    @Override
112    @Deprecated
113    public ILayoutPullParser getParser(String layoutName) {
114        // Studio returns null.
115        return null;
116    }
117
118}
119