/* * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * 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. * * Contributors: * Nuxeo - initial API and implementation * * $Id$ */ package org.nuxeo.common.xmap; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.nuxeo.common.collections.PrimitiveArrays; import org.nuxeo.common.xmap.annotation.XNodeList; import org.w3c.dom.Element; import org.w3c.dom.Node; /** * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> */ @SuppressWarnings({ "SuppressionAnnotation" }) public class XAnnotatedList extends XAnnotatedMember { protected static final ElementVisitor elementListVisitor = new ElementVisitor(); protected static final ElementValueVisitor elementVisitor = new ElementValueVisitor(); protected static final AttributeValueVisitor attributeVisitor = new AttributeValueVisitor(); // indicates the type of the collection components protected Class componentType; protected boolean isNullByDefault; protected XAnnotatedList(XMap xmap, XAccessor setter) { super(xmap, setter); } public XAnnotatedList(XMap xmap, XAccessor setter, XNodeList anno) { super(xmap, setter); path = new Path(anno.value()); trim = anno.trim(); 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) { List<Object> values = new ArrayList<Object>(); if (xao != null) { DOMHelper.visitNodes(ctx, this, base, path, elementListVisitor, values); } else { if (path.attribute != null) { // attribute list DOMHelper.visitNodes(ctx, this, base, path, attributeVisitor, values); } else { // element list DOMHelper.visitNodes(ctx, this, base, path, elementVisitor, values); } } if (isNullByDefault && values.isEmpty()) { return null; } if (type != ArrayList.class) { if (type.isArray()) { if (componentType.isPrimitive()) { // primitive arrays cannot be casted to Object[] return PrimitiveArrays.toPrimitiveArray(values, componentType); } else { return values.toArray((Object[]) Array.newInstance(componentType, values.size())); } } else { try { Collection col = (Collection) type.newInstance(); col.addAll(values); return col; } catch (InstantiationException e) { throw new IllegalArgumentException(e); } catch (IllegalAccessException e) { throw new IllegalArgumentException(e); } } } return values; } @Override public void toXML(Object instance, Element parent) { Object v = accessor.getValue(instance); if (v != null) { Object[] objects = null; if (v instanceof Object[]) { objects = (Object[]) v; } else if (v instanceof List) { objects = ((List) v).toArray(); } else if (v instanceof Collection) { objects = ((Collection) v).toArray(); } else { objects = PrimitiveArrays.toObjectArray(v); } if (objects != null) { if (xao == null) { for (Object o : objects) { String value = valueFactory.serialize(null, o); if (value != null) { Element e = XMLBuilder.addElement(parent, path); XMLBuilder.fillField(e, value, path.attribute); } } } else { for (Object o : objects) { Element e = XMLBuilder.addElement(parent, path); XMLBuilder.toXML(o, e, xao); } } } } } } class ElementVisitor implements DOMHelper.NodeVisitor { @Override public void visitNode(Context ctx, XAnnotatedMember xam, Node node, Collection<Object> result) { result.add(xam.xao.newInstance(ctx, (Element) node)); } } class ElementValueVisitor implements DOMHelper.NodeVisitor { @Override public void visitNode(Context ctx, XAnnotatedMember xam, Node node, Collection<Object> result) { String val = node.getTextContent(); if (xam.trim) { val = val.trim(); } if (xam.valueFactory != null) { result.add(xam.valueFactory.deserialize(ctx, val)); } else { // TODO: log warning? result.add(val); } } } class AttributeValueVisitor implements DOMHelper.NodeVisitor { @Override public void visitNode(Context ctx, XAnnotatedMember xam, Node node, Collection<Object> result) { String val = node.getNodeValue(); if (xam.valueFactory != null) { result.add(xam.valueFactory.deserialize(ctx, val)); } else { // TODO: log warning? result.add(val); } } }