001/* 002 * (C) Copyright 2006-2012 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nuxeo - initial API and implementation 018 * 019 */ 020 021package org.nuxeo.common.xmap; 022 023import org.nuxeo.common.xmap.annotation.XNode; 024import org.w3c.dom.Element; 025 026/** 027 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 028 */ 029public class XAnnotatedMember { 030 031 protected final XAccessor accessor; 032 033 protected Path path; 034 035 protected boolean trim; 036 037 /** The Java type of the described element. */ 038 protected Class<?> type; 039 040 /** Not null if the described object is an xannotated object. */ 041 protected XAnnotatedObject xao; 042 043 /** 044 * The value factory used to transform strings in objects compatible with this member type. In the case of 045 * collection types this factory is used for collection components. 046 */ 047 protected XValueFactory valueFactory; 048 049 protected XAnnotatedMember(XMap xmap, XAccessor accessor) { 050 this.accessor = accessor; 051 } 052 053 public XAnnotatedMember(XMap xmap, XAccessor setter, XNode anno) { 054 accessor = setter; 055 path = new Path(anno.value()); 056 trim = anno.trim(); 057 type = setter.getType(); 058 valueFactory = xmap.getValueFactory(type); 059 if (valueFactory == null && type.isEnum()) { 060 valueFactory = new XValueFactory() { 061 @Override 062 public String serialize(Context arg0, Object arg1) { 063 return ((Enum<?>) arg1).name(); 064 } 065 066 @SuppressWarnings("unchecked") 067 @Override 068 public Object deserialize(Context arg0, String arg1) { 069 @SuppressWarnings("rawtypes") 070 Class<Enum> enumType = (Class<Enum>) type; 071 return Enum.valueOf(enumType, arg1); 072 } 073 }; 074 xmap.setValueFactory(type, valueFactory); 075 } 076 xao = xmap.register(type); 077 } 078 079 protected void setValue(Object instance, Object value) { 080 try { 081 accessor.setValue(instance, value); 082 } catch (IllegalArgumentException e) { 083 throw new IllegalArgumentException( 084 String.format("%s, setter=%s, value=%s", e.getMessage(), accessor, value), e); 085 } 086 } 087 088 public void toXML(Object instance, Element parent) { 089 Element e = XMLBuilder.getOrCreateElement(parent, path); 090 Object v = accessor.getValue(instance); 091 if (xao == null) { 092 if (v != null && valueFactory != null) { 093 String value = valueFactory.serialize(null, v); 094 if (value != null) { 095 096 XMLBuilder.fillField(e, value, path.attribute); 097 } 098 } 099 } else { 100 XMLBuilder.toXML(v, e, xao); 101 } 102 } 103 104 public void process(Context ctx, Element element) { 105 Object value = getValue(ctx, element); 106 if (value != null) { 107 setValue(ctx.getObject(), value); 108 } 109 } 110 111 protected Object getValue(Context ctx, Element base) { 112 if (xao != null) { 113 Element el = (Element) DOMHelper.getElementNode(base, path); 114 if (el == null) { 115 return null; 116 } else { 117 return xao.newInstance(ctx, el); 118 } 119 } 120 // scalar field 121 if (type == Element.class) { 122 // allow DOM elements as values 123 return base; 124 } 125 String val = DOMHelper.getNodeValue(base, path); 126 if (val != null) { 127 if (trim) { 128 val = val.trim(); 129 } 130 if (valueFactory == null) { 131 throw new NullPointerException("Missing XValueFactory for " + type); 132 } 133 return valueFactory.deserialize(ctx, val); 134 } 135 return null; 136 } 137 138}