001/*
002 * HA-JDBC: High-Availability JDBC
003 * Copyright (c) 2004-2007 Paul Ferraro
004 * 
005 * This library is free software; you can redistribute it and/or modify it 
006 * under the terms of the GNU Lesser General Public License as published by the 
007 * Free Software Foundation; either version 2.1 of the License, or (at your 
008 * option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful, but WITHOUT
011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License 
013 * for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public License
016 * along with this library; if not, write to the Free Software Foundation, 
017 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018 * 
019 * Contact: ferraro@users.sourceforge.net
020 */
021package net.sf.hajdbc.sync;
022
023import java.beans.Introspector;
024import java.beans.PropertyDescriptor;
025import java.beans.PropertyEditor;
026import java.beans.PropertyEditorManager;
027import java.util.HashMap;
028import java.util.Map;
029import java.util.Properties;
030
031import net.sf.hajdbc.Messages;
032import net.sf.hajdbc.SynchronizationStrategy;
033
034/**
035 * @author  Paul Ferraro
036 * @since   1.1
037 */
038public class SynchronizationStrategyBuilder
039{
040        private static final String CLASS = "class"; //$NON-NLS-1$
041        
042        private String id;
043        private Class<? extends SynchronizationStrategy> targetClass;
044        private Properties properties;
045        
046        /**
047         * Constructs a new SynchronizationStrategyBuilder.
048         */
049        public SynchronizationStrategyBuilder()
050        {
051                // Do nothing
052        }
053        
054        /**
055         * @return the unique identifier for this synchronization strategy
056         */
057        public String getId()
058        {
059                return this.id;
060        }
061        
062        /**
063         * @return a SynchronizationStrategy instance
064         * @throws Exception
065         */
066        public SynchronizationStrategy buildStrategy() throws Exception
067        {
068                SynchronizationStrategy strategy = this.targetClass.asSubclass(SynchronizationStrategy.class).newInstance();
069                
070                PropertyDescriptor[] descriptors = Introspector.getBeanInfo(this.targetClass).getPropertyDescriptors();
071                
072                Map<String, PropertyDescriptor> propertyDescriptorMap = new HashMap<String, PropertyDescriptor>();
073                
074                for (PropertyDescriptor descriptor: descriptors)
075                {
076                        // Prevent Object.getClass() from being read as a property
077                        if (descriptor.getName().equals(CLASS)) continue;
078                        
079                        propertyDescriptorMap.put(descriptor.getName(), descriptor);
080                }
081                
082                for (Object key: this.properties.keySet())
083                {
084                        String name = (String) key;
085                        
086                        PropertyDescriptor descriptor = propertyDescriptorMap.get(name);
087                        
088                        if (descriptor == null)
089                        {
090                                throw new IllegalArgumentException(Messages.getMessage(Messages.INVALID_PROPERTY, name, this.getClass().getName()));
091                        }
092                        
093                        PropertyEditor editor = PropertyEditorManager.findEditor(descriptor.getPropertyType());
094                        
095                        String textValue = this.properties.getProperty(name);
096                        
097                        try
098                        {
099                                if (editor == null)
100                                {
101                                        throw new Exception();
102                                }
103
104                                editor.setAsText(textValue);
105                        }
106                        catch (Exception e)
107                        {
108                                throw new IllegalArgumentException(Messages.getMessage(Messages.INVALID_PROPERTY_VALUE, textValue, name, this.targetClass.getName()));
109                        }
110                        
111                        descriptor.getWriteMethod().invoke(strategy, editor.getValue());
112                }
113                
114                return strategy;
115        }
116        
117        /**
118         * @param id
119         * @param strategy
120         * @return a builder for this strategy
121         * @throws Exception 
122         */
123        public static SynchronizationStrategyBuilder getBuilder(String id, SynchronizationStrategy strategy) throws Exception
124        {
125                SynchronizationStrategyBuilder builder = new SynchronizationStrategyBuilder();
126                
127                builder.id = id;
128                
129                Class<? extends SynchronizationStrategy> strategyClass = strategy.getClass();
130                
131                builder.targetClass = strategyClass;
132                
133                builder.properties = new Properties();
134                
135                PropertyDescriptor[] descriptors = Introspector.getBeanInfo(strategyClass).getPropertyDescriptors();
136                
137                for (PropertyDescriptor descriptor: descriptors)
138                {
139                        // Prevent Object.getClass() from being written as a property
140                        if (descriptor.getName().equals(CLASS)) continue;
141                        
142                        PropertyEditor editor = PropertyEditorManager.findEditor(descriptor.getPropertyType());
143                        
144                        if (editor == null) continue;
145                        
146                        editor.setValue(descriptor.getReadMethod().invoke(strategy));
147                        
148                        builder.properties.setProperty(descriptor.getName(), editor.getAsText());
149                }
150                
151                return builder;
152        }
153}