Skip to main content
summaryrefslogtreecommitdiffstats
blob: 0c806f8a483e7a9a7a5680b13b94f4a7dcca05e7 (plain) (blame)
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
package org.eclipse.jst.jsf.facelet.core.internal.cm;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.jst.jsf.common.runtime.internal.view.model.common.Namespace;
import org.eclipse.jst.jsf.core.JSFVersion;
import org.eclipse.jst.jsf.designtime.internal.view.model.ITagRegistry;
import org.eclipse.jst.jsf.designtime.internal.view.model.TagRegistryFactory.TagRegistryFactoryException;
import org.eclipse.jst.jsf.facelet.core.internal.registry.FaceletRegistryManager.MyRegistryFactory;
import org.eclipse.jst.jsf.facelet.core.internal.util.ViewUtil;
import org.eclipse.jst.jsf.facelet.core.internal.util.ViewUtil.PrefixEntry;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.CMDocumentFactoryTLD;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDDocument;
import org.eclipse.jst.jsp.core.taglib.ITaglibRecord;
import org.eclipse.jst.jsp.core.taglib.TaglibIndex;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
import org.w3c.dom.Element;

/**
 * Creates CMDocument framework adaptation for Facelet features.
 * 
 * NOTE: this class currently caches state and is NOT THREADSAFE.  Share 
 * instances of this class between unowned classes at your own risk.
 * 
 * @author cbateman
 *
 */
public class FaceletDocumentFactory
{
    private final IProject                        _project;
    private final Map<String, NamespaceCMAdapter> _cmDocuments;
    private final Map<String, TagInfo>    _externalTagInfo;

    /**
     * @param project
     */
    public FaceletDocumentFactory(final IProject project)
    {
        _project = project;
        _cmDocuments = new HashMap<String, NamespaceCMAdapter>(8);
        _externalTagInfo = new HashMap<String, TagInfo>(8);
    }

    /**
     * @param uri
     * @param prefix
     * @return the CMDocument for the uri where prefix is used as its namespace
     * short-form (usually in the context of an XML document instance).
     */
    public CMDocument createCMDocumentForContext(final String uri,
            final String prefix)
    {
        final NamespaceCMAdapter cmDoc = getOrCreateCMDocument(_project, uri);

        if (cmDoc != null)
        {
            return new DocumentNamespaceCMAdapter(cmDoc, prefix);
        }
        return null;
    }

    /**
     * @param element
     * @return the CM model data for element or null if none.
     */
    public CMElementDeclaration createCMElementDeclaration(final Element element)
    {
        final String prefix = element.getPrefix();
        final Map<String, PrefixEntry> namespaces = ViewUtil
                .getDocumentNamespaces(element.getOwnerDocument());
        final PrefixEntry prefixEntry = namespaces.get(prefix);

        if (prefixEntry != null)
        {
            final CMDocument cmDoc = createCMDocumentForContext(prefixEntry
                    .getUri(), prefixEntry.getPrefix());

            if (cmDoc != null)
            {
                return (CMElementDeclaration) cmDoc.getElements().getNamedItem(
                        element.getLocalName());
            }
        }

        return null;
    }

    /**
     * @param ns
     * @return the externa tag info the namespace.  May return a previously
     * cached value. If there is no cached value, then creates it.
     */
    public TagInfo getOrCreateExtraTagInfo(final String ns)
    {
        TagInfo tagInfo = _externalTagInfo.get(ns);

        if (tagInfo == null)
        {
            tagInfo = createExternalTagInfo(ns);
            _externalTagInfo.put(ns, tagInfo);
        }
        return tagInfo;
    }

    /**
     * @return a new external tag info for this namespace
     */
    private TagInfo createExternalTagInfo(final String uri)
    {
        final JSFVersion jsfVersion = JSFVersion.valueOfProject(_project);
        TagInfo tldTagInfo = null;
        if (jsfVersion != null)
        {
            if (jsfVersion.compareTo(JSFVersion.V2_0) >= 0)
            {
                tldTagInfo = new FaceletTagInfo(_project, uri);
            } else
            {
                final ITaglibRecord[] tldrecs = TaglibIndex
                        .getAvailableTaglibRecords(_project.getFullPath());
                FIND_TLDRECORD: for (final ITaglibRecord rec : tldrecs)
                {
                    final String matchUri = rec.getDescriptor().getURI();
                    if (uri.equals(matchUri))
                    {
                        final CMDocumentFactoryTLD factory = new CMDocumentFactoryTLD();
                        tldTagInfo = new MetadataTagInfo(_project,
                                (TLDDocument) factory.createCMDocument(rec));
                        break FIND_TLDRECORD;
                    }
                }

                if (tldTagInfo == null)
                {
                    tldTagInfo = new MetadataTagInfo(_project, uri);
                }
            }
        }
        return tldTagInfo;
    }

    private NamespaceCMAdapter getOrCreateCMDocument(final IProject project,
            final String uri)
    {
        NamespaceCMAdapter adapter = _cmDocuments.get(uri);

        if (adapter == null)
        {
            final MyRegistryFactory factory = new MyRegistryFactory();

            ITagRegistry registry;
            try
            {
                registry = factory.createTagRegistry(project);
                if (registry != null)
                {
                    final Namespace ns = registry.getTagLibrary(uri);

                    if (ns != null)
                    {
                        adapter = new NamespaceCMAdapter(ns, project);
                        _cmDocuments.put(uri, adapter);
                    }
                }
            }
            catch (final TagRegistryFactoryException e)
            {
                // fall-through
            }
        }
        return adapter;
    }

}

Back to the top