/** * Copyright (2012) Schibsted ASA * This file is part of Possom. * * Possom is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Possom 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. * * You should have received a copy of the GNU Lesser General Public License * along with Possom. If not, see <http://www.gnu.org/licenses/>. */ package no.sesat.search.mode.config; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import org.apache.log4j.Logger; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; /** Provides a way for default named xml-named-attributes to be deserialised into javabean getters and setters. * Including support for sesat's polymorphic xml configurations. * * From Issue SKER4404: (Automatically assign config settings in readSearchConfiguration where there is a setter). * http://sesat.no/scarab/issues/id/SKER4404 * * * @version $id$ */ public final class ModesSearchConfigurationDeserializer { // Constants ----------------------------------------------------- private static final Logger LOG = Logger.getLogger(ModesSearchConfigurationDeserializer.class); // Static -------------------------------------------------------- public static void readSearchConfiguration( final SearchConfiguration.ModesW3cDomDeserialiser config, final Element element, final SearchConfiguration inherit) { final Map<String, PropertyDescriptor> descriptors = getDescriptors(config); final NamedNodeMap attribs = element.getAttributes(); for (int i = 0; i < attribs.getLength(); i++) { final Node attrib = attribs.item(i); final String name = attrib.getNodeName(); if (!"inherit".equals(name)) { final StringBuilder beanName = new StringBuilder(name); for (int j = 0; j < beanName.length(); ++j) { final char c = beanName.charAt(j); if ('-' == c) { beanName.replace(j, j + 2, String.valueOf(Character.toUpperCase(beanName.charAt(j + 1)))); ++j; } } final PropertyDescriptor descriptor = descriptors.get(beanName.toString()); if (null != descriptor) { final Method setter = descriptor.getWriteMethod(); if (null != setter) { final Class<?> type = setter.getParameterTypes()[0]; Object value = null; String valueString = attrib.getNodeValue(); if (type == String.class){ value = valueString; }else if (type == String[].class){ value = valueString.split(","); }else if (type == int.class || type == Integer.class){ value = Integer.parseInt(valueString); }else if (type == boolean.class || type == Boolean.class){ value = Boolean.parseBoolean(valueString); }else if (type == char.class || type == Character.class) { value = valueString.charAt(0); if (valueString.length() > 1){ LOG.error("Setting char attribute where input was more then a character long"); } } else { LOG.error("Failed to set attribute " + setter.getName() + ", unnsuported type."); } if (null != value) { try { setter.invoke(config, value); } catch (Exception e) { LOG.info("Failed to set attribute with name: " + setter.getName() + "(" + type + ")."); } } } else { LOG.warn("Missing setter for: " + beanName.toString()); } descriptors.remove(beanName.toString()); } else { LOG.warn("Unknown attribute in configfile: " + beanName.toString()); } } } // inherited attributes if (inherit != null) { readInheritedValues(config, inherit, descriptors); } } // Constructor ------------------------------------------------------- /** * Hide default constructor. * Class is intended only as a static utility. */ private ModesSearchConfigurationDeserializer(){} // Private ------------------------------------------------------- private static Map<String, PropertyDescriptor> getDescriptors( final SearchConfiguration.ModesW3cDomDeserialiser config){ final Map<String, PropertyDescriptor> descriptors = new HashMap<String, PropertyDescriptor>(); final String[] path = new String[]{"no.sesat.search.mode.config"}; Introspector.setBeanInfoSearchPath(path); try { final BeanInfo info = Introspector.getBeanInfo(config.getClass()); for (PropertyDescriptor d : info.getPropertyDescriptors()) { descriptors.put(d.getName(), d); } } catch (IntrospectionException e) { LOG.error("Failed to get bean info from class " + config.getClass().getSimpleName(), e); } return descriptors; } private static void readInheritedValues( final SearchConfiguration.ModesW3cDomDeserialiser config, final SearchConfiguration inherit, final Map<String, PropertyDescriptor> descriptors){ for (PropertyDescriptor d : descriptors.values()) { final Method getter = d.getReadMethod(); if (getter != null && getter.getDeclaringClass().isInstance(inherit)) { Object value = null; try { value = getter.invoke(inherit); } catch (Exception e) { LOG.error("Failed to get value from " + inherit.getName(), e); } if (null != value) { final Method setter = d.getWriteMethod(); if (null != setter) { try { setter.invoke(config, value); } catch (Exception e) { LOG.error( "Failed to set value from " + inherit.getName() + " on " + config.getName(), e); } } } } } } }