/*
* (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl.html
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* Contributors:
* Nuxeo - initial API and implementation
*
* $Id$
*/
package org.nuxeo.common.xmap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.common.xmap.annotation.XNodeMap;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
*/
@SuppressWarnings( { "SuppressionAnnotation" })
public class XAnnotatedMap extends XAnnotatedList {
protected static final ElementMapVisitor elementMapVisitor = new ElementMapVisitor();
protected static final ElementValueMapVisitor elementVisitor = new ElementValueMapVisitor();
protected static final AttributeValueMapVisitor attributeVisitor = new AttributeValueMapVisitor();
protected final Path key;
protected final boolean isNullByDefault;
public XAnnotatedMap(XMap xmap, XAccessor setter, XNodeMap anno) {
super(xmap, setter);
path = new Path(anno.value());
trim = anno.trim();
key = new Path(anno.key());
type = anno.type();
componentType = anno.componentType();
valueFactory = xmap.getValueFactory(componentType);
xao = xmap.register(componentType);
isNullByDefault = anno.nullByDefault();
}
@SuppressWarnings("unchecked")
@Override
protected Object getValue(Context ctx, Element base)
throws IllegalAccessException, InstantiationException {
Map<String, Object> values = (Map) type.newInstance();
if (xao != null) {
DOMHelper.visitMapNodes(ctx, this, base, path, elementMapVisitor,
values);
} else {
if (path.attribute != null) {
// attribute list
DOMHelper.visitMapNodes(ctx, this, base, path,
attributeVisitor, values);
} else {
// element list
DOMHelper.visitMapNodes(ctx, this, base, path, elementVisitor,
values);
}
}
if (isNullByDefault && values.isEmpty()) {
values = null;
}
return values;
}
@Override
public void toXML(Object instance, Element parent) throws Exception {
Object v = accessor.getValue(instance);
if (v != null && v instanceof Map<?, ?>) {
Map<String, ?> map = (Map<String, ?>) v;
if (xao == null) {
for (Map.Entry<String, ?> entry : map.entrySet()) {
String entryKey = entry.getKey();
String value = valueFactory.serialize(null,
entry.getValue());
Element e = XMLBuilder.addElement(parent, path);
Element keyElement = XMLBuilder.getOrCreateElement(e, key);
XMLBuilder.fillField(keyElement, entryKey, key.attribute);
XMLBuilder.fillField(e, value, null);
}
} else {
for (Map.Entry<String, ?> entry : map.entrySet()) {
String entryKey = entry.getKey();
Element e = XMLBuilder.addElement(parent, path);
Element keyElement = XMLBuilder.getOrCreateElement(e, key);
XMLBuilder.fillField(keyElement, entryKey, key.attribute);
XMLBuilder.toXML(entry.getValue(), e, xao);
}
}
}
}
}
class ElementMapVisitor implements DOMHelper.NodeMapVisitor {
private static final Log log = LogFactory.getLog(ElementMapVisitor.class);
public void visitNode(Context ctx, XAnnotatedMember xam, Node node,
String key, Map<String, Object> result) {
try {
result.put(key, xam.xao.newInstance(ctx, (Element) node));
} catch (Exception e) {
log.error(e, e);
}
}
}
class ElementValueMapVisitor implements DOMHelper.NodeMapVisitor {
public void visitNode(Context ctx, XAnnotatedMember xam, Node node,
String key, Map<String, Object> result) {
String val = node.getTextContent();
if (xam.trim) {
val = val.trim();
}
if (xam.valueFactory != null) {
result.put(key, xam.valueFactory.deserialize(ctx, val));
} else {
// TODO: log warning?
result.put(key, val);
}
}
}
class AttributeValueMapVisitor implements DOMHelper.NodeMapVisitor {
public void visitNode(Context ctx, XAnnotatedMember xam, Node node,
String key, Map<String, Object> result) {
String val = node.getNodeValue();
if (xam.valueFactory != null) {
result.put(key, xam.valueFactory.deserialize(ctx, val));
} else {
// TODO: log warning?
result.put(key, val);
}
}
}