blob: 49737f55ff6a8ac0b0ba9f70dc6d27dae6099da9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2008 Oracle Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Oracle Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.jsf.designtime.internal.view;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jst.jsf.common.runtime.internal.model.ViewObject;
import org.eclipse.jst.jsf.common.runtime.internal.model.component.ComponentFactory;
import org.eclipse.jst.jsf.common.runtime.internal.model.component.ComponentInfo;
import org.eclipse.jst.jsf.designtime.context.DTFacesContext;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* A component tree construction strategy based on XML view definition
*
* @author cbateman
*
*/
public class XMLComponentTreeConstructionStrategy extends
ComponentTreeConstructionStrategy<Node, IDocument>
{
private final XMLViewDefnAdapter _adapter;
// private final XMLViewObjectConstructionStrategy
// _objectConstructionStrategy;
private final IProject _project;
/**
* @param adapter
* @param project
*/
public XMLComponentTreeConstructionStrategy(
final XMLViewDefnAdapter adapter, final IProject project)
{
_adapter = adapter;
_project = project;
}
@Override
public ComponentInfo createComponentTree(final DTFacesContext context,
final DTUIViewRoot viewRoot)
{
final IDocument container = _adapter.getContainer(context, viewRoot
.getViewId());
final List<Node> roots = _adapter.getViewDefnRoots(container);
if (roots.size() > 0)
{
final IAdaptable adaptable = viewRoot.getServices();
XMLViewObjectMappingService tagMappingService = null;
if (adaptable != null)
{
tagMappingService = (XMLViewObjectMappingService) adaptable
.getAdapter(XMLViewObjectMappingService.class);
}
final XMLViewObjectConstructionStrategy objectConstructionStrategy =
new XMLViewObjectConstructionStrategy(
_adapter, new ComponentConstructionData(0, null, _project,
container), tagMappingService);
objectConstructionStrategy.getConstructionData().setIdCounter(0);
// can only handle a single root for XML; should be the DOM root
return buildComponentTree(roots.get(0), viewRoot, container,
objectConstructionStrategy);
}
return viewRoot;
}
private ComponentInfo buildComponentTree(final Node root,
final DTUIViewRoot viewRoot, final IDocument document,
final XMLViewObjectConstructionStrategy objectConstructionStrategy)
{
final ComponentInfo dummyRoot = ComponentFactory.createComponentInfo(
null, null, null, true);
// populate the dummy root
recurseDOMModel(root, dummyRoot, document, objectConstructionStrategy);
// try to extract the view defined root from the dummyRoot and update
// 'root' with its children.
populateViewRoot(viewRoot, dummyRoot.getChildren());
return viewRoot;
}
/**
* Tries to find the view defined view root in children and use it populate
* viewRoot. Children may sub-class to a different algorithm or, in some
* cases create an implicit (i.e. Facelets does this) view root if one is
* not explicitly created by the view definition.
*
* Regardless of the strategy, the following post-conditions must be true
*
* To the extend that children represent the top-level objects in the view
* under the presumed root, viewRoot must be populated with them either
* directly if the creation of a view root is implicit (i.e. Facelets) or
* through a valid view root declaration found in the view definition (i.e.
* f:view in JSP) found the children list.
*
* The default behaviour assumes the JSP case.
*
* TODO: add validation cases for missing view roots in JSP.
*
* @param viewRoot
* @param children
*/
protected void populateViewRoot(final DTUIViewRoot viewRoot,
final List children)
{
ComponentInfo foundRoot = null;
// TODO: additional cases:
// 1) Valid case: view is a fragment and has one or more non-view root
// children
// 2) Invalid case: not a fragment and has no view root
// 3) Invalid case: any definition and has more than one view root
// 4) Invalid case: any definition and has component siblings to the
// view root
FIND_VIEWROOT: for (final Iterator it = children.iterator(); it
.hasNext();)
{
final ComponentInfo topLevelChild = (ComponentInfo) it.next();
if ("javax.faces.ViewRoot".equals(topLevelChild //$NON-NLS-1$
.getComponentTypeInfo().getComponentType()))
{
foundRoot = topLevelChild;
break FIND_VIEWROOT;
}
}
if (foundRoot != null)
{
for (final Iterator it = foundRoot.getChildren().iterator(); it
.hasNext();)
{
final ComponentInfo child = (ComponentInfo) it.next();
final String facetName = foundRoot.getFacetName(child);
// if not a facet, add as a normal child
if (facetName == null)
{
viewRoot.addChild(child);
}
// if it is a facet, add as a facet
else
{
viewRoot.addFacet(facetName, child);
}
}
}
}
private void recurseDOMModel(final Node node, final ComponentInfo parent,
final IDocument document,
XMLViewObjectConstructionStrategy objectConstructionStrategy)
{
ViewObject mappedObject = null;
objectConstructionStrategy.getConstructionData().setParent(parent);
mappedObject = _adapter.mapToViewObject(node,
objectConstructionStrategy, document);
ComponentInfo newParent = parent;
if (mappedObject instanceof ComponentInfo)
{
parent.addChild((ComponentInfo) mappedObject);
newParent = (ComponentInfo) mappedObject;
}
final NodeList children = node.getChildNodes();
final int numChildren = children.getLength();
for (int i = 0; i < numChildren; i++)
{
recurseDOMModel(children.item(i), newParent, document,
objectConstructionStrategy);
}
}
}