aboutsummaryrefslogtreecommitdiff
path: root/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/model/UiManifestElementNode.java
blob: 0151d4d46f4b2a2613a4578b974b19137e0b634f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.eclipse.org/org/documents/epl-v10.php
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.ide.eclipse.adt.internal.editors.manifest.model;

import com.android.SdkConstants;
import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.AndroidManifestDescriptors;
import com.android.ide.eclipse.adt.internal.editors.manifest.descriptors.ManifestElementDescriptor;
import com.android.ide.eclipse.adt.internal.editors.uimodel.UiAttributeNode;
import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;

import org.w3c.dom.Element;

/**
 * Represents an XML node that can be modified by the user interface in the XML editor.
 * <p/>
 * Each tree viewer used in the application page's parts needs to keep a model representing
 * each underlying node in the tree. This interface represents the base type for such a node.
 * <p/>
 * Each node acts as an intermediary model between the actual XML model (the real data support)
 * and the tree viewers or the corresponding page parts.
 * <p/>
 * Element nodes don't contain data per se. Their data is contained in their attributes
 * as well as their children's attributes, see {@link UiAttributeNode}.
 * <p/>
 * The structure of a given {@link UiElementNode} is declared by a corresponding
 * {@link ElementDescriptor}.
 */
public final class UiManifestElementNode extends UiElementNode {

    /**
     * Creates a new {@link UiElementNode} described by a given {@link ElementDescriptor}.
     *
     * @param elementDescriptor The {@link ElementDescriptor} for the XML node. Cannot be null.
     */
    public UiManifestElementNode(ManifestElementDescriptor elementDescriptor) {
        super(elementDescriptor);
    }

    /**
     * Computes a short string describing the UI node suitable for tree views.
     * Uses the element's attribute "android:name" if present, or the "android:label" one
     * followed by the element's name if not repeated.
     *
     * @return A short string describing the UI node suitable for tree views.
     */
    @Override
    public String getShortDescription() {
        AndroidTargetData target = getAndroidTarget();
        AndroidManifestDescriptors manifestDescriptors = null;
        if (target != null) {
            manifestDescriptors = target.getManifestDescriptors();
        }

        String name = getDescriptor().getUiName();

        if (manifestDescriptors != null &&
                getXmlNode() != null &&
                getXmlNode() instanceof Element &&
                getXmlNode().hasAttributes()) {

            // Application and Manifest nodes have a special treatment: they are unique nodes
            // so we don't bother trying to differentiate their strings and we fall back to
            // just using the UI name below.
            ElementDescriptor desc = getDescriptor();
            if (desc != manifestDescriptors.getManifestElement() &&
                    desc != manifestDescriptors.getApplicationElement()) {
                Element elem = (Element) getXmlNode();
                String attr = _Element_getAttributeNS(elem,
                                    SdkConstants.NS_RESOURCES,
                                    AndroidManifestDescriptors.ANDROID_NAME_ATTR);
                if (attr == null || attr.length() == 0) {
                    attr = _Element_getAttributeNS(elem,
                                    SdkConstants.NS_RESOURCES,
                                    AndroidManifestDescriptors.ANDROID_LABEL_ATTR);
                }
                if (attr != null && attr.length() > 0) {
                    // If the ui name is repeated in the attribute value, don't use it.
                    // Typical case is to avoid ".pkg.MyActivity (Activity)".
                    if (attr.contains(name)) {
                        return attr;
                    } else {
                        return String.format("%1$s (%2$s)", attr, name);
                    }
                }
            }
        }

        return String.format("%1$s", name);
    }

    /**
     * Retrieves an attribute value by local name and namespace URI.
     * <br>Per [<a href='http://www.w3.org/TR/1999/REC-xml-names-19990114/'>XML Namespaces</a>]
     * , applications must use the value <code>null</code> as the
     * <code>namespaceURI</code> parameter for methods if they wish to have
     * no namespace.
     * <p/>
     * Note: This is a wrapper around {@link Element#getAttributeNS(String, String)}.
     * In some versions of webtools, the getAttributeNS implementation crashes with an NPE.
     * This wrapper will return null instead.
     *
     * @see Element#getAttributeNS(String, String)
     * @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=318108">https://bugs.eclipse.org/bugs/show_bug.cgi?id=318108</a>
     * @return The result from {@link Element#getAttributeNS(String, String)} or or an empty string.
     */
    private String _Element_getAttributeNS(Element element,
            String namespaceURI,
            String localName) {
        try {
            return element.getAttributeNS(namespaceURI, localName);
        } catch (Exception ignore) {
            return "";
        }
    }
}