blob: 6eb5021f94d74753fbccc030e9a2632fbf9cb34d [file] [log] [blame]
package org.eclipse.jst.jsf.facelet.core.internal.view;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jst.jsf.context.IModelContext;
import org.eclipse.jst.jsf.context.resolver.structureddocument.IDOMContextResolver;
import org.eclipse.jst.jsf.context.resolver.structureddocument.IStructuredDocumentContextResolverFactory;
import org.eclipse.jst.jsf.context.resolver.structureddocument.internal.ITextRegionContextResolver;
import org.eclipse.jst.jsf.context.structureddocument.IStructuredDocumentContext;
import org.eclipse.jst.jsf.context.structureddocument.IStructuredDocumentContextFactory;
import org.eclipse.jst.jsf.core.internal.JSFCorePlugin;
import org.eclipse.jst.jsf.designtime.context.DTFacesContext;
import org.eclipse.jst.jsf.designtime.internal.view.TaglibBasedViewDefnAdapter;
import org.eclipse.jst.jsf.designtime.internal.view.IDTViewHandler.ViewHandlerException;
import org.eclipse.jst.jsf.designtime.internal.view.IDTViewHandler.ViewHandlerException.Cause;
import org.eclipse.jst.jsf.designtime.internal.view.model.ITagRegistry;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
/**
* The facelet view definition adapter.
*
* @author cbateman
*
*/
public class FaceletViewDefnAdapter extends TaglibBasedViewDefnAdapter
{
FaceletViewDefnAdapter(final ITagRegistry tagRegistry)
{
super(tagRegistry);
}
@Override
public IDocument getContainer(final DTFacesContext context, final String viewId)
{
final IResource viewDefn = context.adaptContextObject();
if (viewDefn instanceof IFile)
{
final IFile viewDefnFile = (IFile) viewDefn;
IStructuredModel model = null;
try
{
model = StructuredModelManager.getModelManager()
.getModelForRead(viewDefnFile);
return model.getStructuredDocument();
}
catch (final IOException e)
{
JSFCorePlugin.log(e, "Acquiring model for view root"); //$NON-NLS-1$
}
catch (final CoreException e)
{
JSFCorePlugin.log(e, "Acquiring model for view root"); //$NON-NLS-1$
}
finally
{
if (model != null)
{
model.releaseFromRead();
}
}
}
return null;
}
@Override
public DTELExpression getELExpression(final IModelContext genericContext)
throws ViewHandlerException
{
final IStructuredDocumentContext context = (IStructuredDocumentContext) genericContext
.getAdapter(IStructuredDocumentContext.class);
if (context == null)
{
throw new ViewHandlerException(Cause.EL_NOT_FOUND);
}
final ITextRegionContextResolver resolver =
IStructuredDocumentContextResolverFactory.INSTANCE
.getTextRegionResolver(context);
if (resolver != null)
{
final String regionType = resolver.getRegionType();
int startOffset = resolver.getStartOffset();
int relativeOffset = context.getDocumentPosition() - startOffset;
if (DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE.equals(regionType))
{
final String attributeText = resolver.getRegionText();
int elOpenIdx = attributeText.indexOf("#"); //$NON-NLS-1$
if (elOpenIdx >= 0 && elOpenIdx < relativeOffset
&& elOpenIdx+1 < attributeText.length()
&& attributeText.charAt(elOpenIdx+1) == '{')
{
// we may have a hit
int elCloseIdx = attributeText.indexOf('}', elOpenIdx+1);
if (elCloseIdx != -1)
{
final IStructuredDocumentContext elContext =
IStructuredDocumentContextFactory.INSTANCE.getContext(
context.getStructuredDocument(), resolver
.getStartOffset()+elOpenIdx+2);
final String elText = attributeText.substring(
elOpenIdx + 2, elCloseIdx);
return new DTELExpression(elContext, elText);
}
}
}
}
return null;
}
@Override
public String getNamespace(final Element element, final IDocument doc)
{
final Map<String, PrefixEntry> namespaces = getDocumentNamespaces(element
.getOwnerDocument());
final String prefix = element.getPrefix();
final PrefixEntry prefixEntry = namespaces.get(prefix);
if (prefixEntry != null)
{
return prefixEntry.getUri();
}
return null;
}
@Override
public String getPrefix(String namespace, IDocument document)
{
if (namespace == null || "".equals(namespace.trim())) //$NON-NLS-1$
{
return null;
}
final IStructuredDocumentContext context = IStructuredDocumentContextFactory.INSTANCE
.getContext(document, -1);
if (context != null)
{
final IDOMContextResolver resolver = IStructuredDocumentContextResolverFactory.INSTANCE
.getDOMContextResolver(context);
if (resolver != null)
{
final Document xmlDoc = resolver.getDOMDocument();
if (xmlDoc != null)
{
Map<String, PrefixEntry> map = getDocumentNamespaces(xmlDoc);
for (final Map.Entry<String, PrefixEntry> mapEntry : map.entrySet())
{
if (namespace.equals(mapEntry.getValue().getUri()))
{
return mapEntry.getKey();
}
}
}
}
}
return null;
}
/**
* @param doc
* @return map of available prefices in doc keyed by tag prefix
*/
private Map<String, PrefixEntry> getDocumentNamespaces(final Document doc)
{
final Map<String, PrefixEntry> namespaces = new HashMap<String, PrefixEntry>();
final Element rootElement = doc.getDocumentElement();
if (rootElement != null)
{
final NamedNodeMap attrs = rootElement.getAttributes();
for (int i = 0; i < attrs.getLength(); i++)
{
final Attr a = (Attr) attrs.item(i);
final PrefixEntry ns = PrefixEntry.parseNamespace(a);
if (ns != null)
{
namespaces.put(ns._prefix, ns);
}
}
}
return namespaces;
}
private static class PrefixEntry
{
private static final String XMLNS = "xmlns"; //$NON-NLS-1$
private final String _uri;
private final String _prefix;
public static PrefixEntry parseNamespace(final Attr attr)
{
final String prefix = attr.getPrefix();
if (XMLNS.equals(prefix))
{
final String prefixName = attr.getLocalName();
if (prefixName != null)
{
final String uri = attr.getNodeValue();
if (uri != null)
{
return new PrefixEntry(uri, prefixName);
}
}
}
return null;
}
public PrefixEntry(final String uri, final String prefix)
{
_uri = uri;
_prefix = prefix;
}
public final String getUri()
{
return _uri;
}
@Override
public int hashCode()
{
return _uri.hashCode();
}
@Override
public boolean equals(final Object obj)
{
return _uri.equals(obj);
}
}
}