+ @SuppressWarnings("unchecked")
+ public Object nodeToBean(Node node) throws RepositoryException {
+
+ String clssName = node.getProperty(classProperty).getValue()
+ .getString();
+
+ if (log.isTraceEnabled())
+ log.debug("Map node " + node.getPath() + " to bean " + clssName);
+
+ BeanWrapper beanWrapper = createBeanWrapper(loadClass(clssName));
+
+ // process properties
+ PropertyIterator propIt = node.getProperties();
+ props: while (propIt.hasNext()) {
+ Property prop = propIt.nextProperty();
+ if (!beanWrapper.isWritableProperty(prop.getName()))
+ continue props;
+
+ PropertyDescriptor pd = beanWrapper.getPropertyDescriptor(prop
+ .getName());
+ Class propClass = pd.getPropertyType();
+
+ // list
+ if (propClass != null && List.class.isAssignableFrom(propClass)) {
+ List<Object> lst = new ArrayList<Object>();
+ Class<?> valuesClass = classFromProperty(prop);
+ if (valuesClass != null)
+ for (Value value : prop.getValues()) {
+ lst.add(asObject(value, valuesClass));
+ }
+ continue props;
+ }
+
+ Object value = asObject(prop.getValue(), pd.getPropertyType());
+ if (value != null)
+ beanWrapper.setPropertyValue(prop.getName(), value);
+ }
+
+ // process children nodes
+ NodeIterator nodeIt = node.getNodes();
+ nodes: while (nodeIt.hasNext()) {
+ Node childNode = nodeIt.nextNode();
+ String name = childNode.getName();
+ if (!beanWrapper.isWritableProperty(name))
+ continue nodes;
+
+ PropertyDescriptor pd = beanWrapper.getPropertyDescriptor(name);
+ Class propClass = pd.getPropertyType();
+
+ if (propClass != null && List.class.isAssignableFrom(propClass)) {
+ String lstClass = childNode.getProperty(classProperty)
+ .getString();
+ List<Object> lst;
+ try {
+ lst = (List<Object>) loadClass(lstClass).newInstance();
+ } catch (Exception e) {
+ lst = new ArrayList<Object>();
+ }
+
+ NodeIterator valuesIt = childNode.getNodes();
+ while (valuesIt.hasNext()) {
+ Node lstValueNode = valuesIt.nextNode();
+ Object lstValue = nodeToBean(lstValueNode);
+ lst.add(lstValue);
+ }
+
+ beanWrapper.setPropertyValue(name, lst);
+ continue nodes;
+ }
+
+ if (propClass != null && Map.class.isAssignableFrom(propClass)) {
+ String mapClass = childNode.getProperty(classProperty)
+ .getString();
+ Map<Object, Object> map;
+ try {
+ map = (Map<Object, Object>) loadClass(mapClass)
+ .newInstance();
+ } catch (Exception e) {
+ map = new HashMap<Object, Object>();
+ }
+
+ // properties
+ PropertyIterator keysPropIt = childNode.getProperties();
+ keyProps: while (keysPropIt.hasNext()) {
+ Property keyProp = keysPropIt.nextProperty();
+ // FIXME: use property editor
+ String key = keyProp.getName();
+ if (classProperty.equals(key))
+ continue keyProps;
+
+ Class keyPropClass = classFromProperty(keyProp);
+ if (keyPropClass != null) {
+ Object mapValue = asObject(keyProp.getValue(),
+ keyPropClass);
+ map.put(key, mapValue);
+ }
+ }
+
+ // node
+ NodeIterator keysIt = childNode.getNodes();
+ while (keysIt.hasNext()) {
+ Node mapValueNode = keysIt.nextNode();
+ // FIXME: use property editor
+ Object key = mapValueNode.getName();
+
+ Object mapValue = nodeToBean(mapValueNode);
+
+ map.put(key, mapValue);
+ }
+ beanWrapper.setPropertyValue(name, map);
+ continue nodes;
+ }
+
+ // default
+ Object value = nodeToBean(childNode);
+ beanWrapper.setPropertyValue(name, value);
+
+ }
+ return beanWrapper.getWrappedInstance();
+ }
+
+ protected void beanToNode(BeanWrapper beanWrapper, Node node)
+ throws RepositoryException {
+ if (log.isTraceEnabled())