/*
* � Copyright IBM Corp. 2013
*
* Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* 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.ibm.xsp.test.framework.serialize;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import com.ibm.xsp.test.framework.XspTestUtil;
import com.ibm.xsp.util.TypedUtil;
/**
* This class is package-private because it is only used by {@link StateManagerTestImpl}.
*/
/*package-private*/ class Node implements Serializable {
private static final long serialVersionUID = 1L;
private List<Node> _kids = new ArrayList<Node>();
private Map<String, Node> _facets = new HashMap<String, Node>();
private String _id = null;
private String _className = null;
public Node(UIComponent c) {
validate(c);
_id = c.getId();
_className = c.getClass().getName();
List<UIComponent> children = TypedUtil.getChildren(c);
for(int i=0; i<children.size(); i++) {
UIComponent child = children.get(i);
if(child.isTransient()) {
continue;
}
Node kid = new Node(child);
_kids.add(kid);
}
if( c.getFacetCount() > 0 ){
Map<String, UIComponent> map = TypedUtil.getFacets(c);
for (Map.Entry<String, UIComponent> pair : map.entrySet()) {
String name = pair.getKey();
UIComponent facet = pair.getValue();
if(facet.isTransient()) {
continue;
}
Node node = new Node(facet);
_facets.put(name, node);
}
}
}
public UIComponent restore(ClassLoader cl) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
UIComponent comp = restoreInstance(cl);
restoreTree(cl, comp);
return comp;
}
/**
* @param cl
* @param comp
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IllegalAccessException
*/
public void restoreTree(ClassLoader cl, UIComponent comp)
throws ClassNotFoundException, InstantiationException,
IllegalAccessException {
for(int i=0; i<_kids.size(); i++) {
Node node = _kids.get(i);
UIComponent kid = node.restoreInstance(cl);
TypedUtil.getChildren(comp).add(kid);
node.restoreTree(cl, kid);
}
Iterator<String> names = _facets.keySet().iterator();
while(names.hasNext()) {
String name = names.next().toString();
Node node = _facets.get(name);
UIComponent facet = node.restoreInstance(cl);
TypedUtil.getFacets(comp).put(name, facet);
node.restoreTree(cl, facet);
}
}
/**
* @param cl
* @return
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public UIComponent restoreInstance(ClassLoader cl)
throws ClassNotFoundException, IllegalAccessException,
InstantiationException {
Class<?> c = cl.loadClass(_className);
UIComponent comp = (UIComponent) c.newInstance();
comp.setId(_id);
return comp;
}
private void validate(UIComponent uic) {
try {
//components must have public, zero-arg construtor
uic.getClass().newInstance();
} catch(Exception e) {
String component = getStructureName(uic);
throw new IllegalArgumentException("Invalid component class: "+e+"\n\t\t"+component, e);
}
}
private static String getStructureName(UIComponent c) {
if (c == null) {
return "";
}
String id = (c instanceof UIViewRoot) ? ((UIViewRoot)c).getViewId() : c.getId();
return getStructureName(c.getParent()) + ">" + XspTestUtil.getShortClass(c.getClass()) + "(id=" + id + ")";
}
}