001 package com.sptci.echo2;
002
003 import java.io.Serializable;
004
005 import java.lang.reflect.InvocationTargetException;
006 import java.lang.reflect.Method;
007
008 import java.util.ArrayList;
009 import java.util.List;
010 import java.util.Map;
011 import java.util.logging.Logger;
012
013 import nextapp.echo2.app.ListBox;
014 import nextapp.echo2.app.SelectField;
015 import nextapp.echo2.app.button.ToggleButton;
016 import nextapp.echo2.app.list.DefaultListModel;
017
018 import com.sptci.ReflectionUtility;
019
020 /**
021 * An <code>updater</code> used to update UI containers with data from
022 * JavaBean objects.
023 *
024 * <p>Copyright 2006 Sans Pareil Technologies, Inc.</p>
025 * @author Rakesh Vidyadharan 2006-02-07
026 * @version $Id: ViewUpdater.java,v 1.3 2006/02/15 00:48:26 rakesh Exp $
027 */
028 public class ViewUpdater extends Updater implements Serializable
029 {
030 /**
031 * The logger used to log errors/warnings to.
032 */
033 private static transient final Logger logger =
034 Logger.getLogger( "com.sptci.echo2.ViewUpdater" );
035
036 /**
037 * Create a new instance with the specified UI container and java
038 * bean.
039 *
040 * @param uiContainer The {@link #uiContainer} to use.
041 * @param bean The {@link #bean} to use.
042 */
043 public ViewUpdater( Object uiContainer, Object bean )
044 {
045 super( uiContainer, bean );
046 }
047
048 /**
049 * Update the fields of the {@link #uiContainer} with the data in
050 * similarly named fields in {@link #bean}.
051 *
052 * @see ReflectionUtility#fetchField
053 * @see #updateComponent
054 * @throws BindingException If errors are encountered while
055 * accessing or setting the fields.
056 */
057 public void update()
058 {
059 try
060 {
061 for ( Map.Entry<String, Object> entry : beanValues().entrySet() )
062 {
063 Object object =
064 ReflectionUtility.fetchObject( entry.getKey(), uiContainer );
065 updateComponent( object, entry.getValue() );
066 }
067 }
068 catch ( Throwable t )
069 {
070 throw new BindingException( t );
071 }
072 }
073
074 /**
075 * Update the value of the specified code using the specified
076 * value.
077 *
078 * @see #processMap
079 * @see #updateSelectField
080 * @param object The UI component that is to be updated.
081 * @param value The value with which to update the object.
082 * @throws IllegalAccessException If a custom security policy
083 * restricts access to the bean fields.
084 * @throws InvocationTargetException If the accessor method for
085 * the field could not be invoked successfully.
086 */
087 protected void updateComponent( Object object, Object value )
088 throws IllegalAccessException, InvocationTargetException
089 {
090 if ( object instanceof nextapp.echo2.app.text.TextComponent )
091 {
092 Method method = ReflectionUtility.fetchMethod( object,
093 "setText", new Class[] { java.lang.String.class } );
094 method.invoke( object, value );
095 }
096 else if ( object instanceof java.util.Map )
097 {
098 processMap( (Map<String, ToggleButton>) object,
099 (Map<String, Boolean>) value );
100 }
101 else if ( object instanceof nextapp.echo2.app.SelectField )
102 {
103 updateSelectField( (SelectField) object, (List<ListItem>) value );
104 }
105 else if ( object instanceof nextapp.echo2.app.ListBox )
106 {
107 updateListBox( (ListBox) object, (List<ListItem>) value );
108 }
109 }
110
111 /**
112 * Update <code>ToggleButton</code> UI components.
113 *
114 * @param ui The map that contains the name and selected state
115 * of the toggle button.
116 * @param value The new mappings to apply to the UI component.
117 */
118 protected void processMap( Map<String, ToggleButton> ui,
119 Map<String, Boolean> value )
120 {
121 for ( Map.Entry<String, ToggleButton> entry : ui.entrySet() )
122 {
123 String key = entry.getKey();
124
125 if ( key != null && key.indexOf( ">" ) != -1 )
126 {
127 key = key.substring( key.indexOf( ">" ) + 1 );
128 }
129
130 if ( value.containsKey( key ) )
131 {
132 entry.getValue().setSelected(
133 ( (Boolean) value.get( key ) ).booleanValue() );
134 }
135 else
136 {
137 logger.info( "No key " + key + " found in map" );
138 }
139 }
140 }
141
142 /**
143 * Update a <code>SelectField</code> UI component.
144 *
145 * @param selectField The UI component that is to be updated.
146 * @param list The updated list data to apply to the UI component.
147 */
148 protected void updateSelectField( SelectField selectField,
149 List<ListItem> list )
150 {
151 DefaultListModel model = new DefaultListModel();
152 selectField.setSelectedIndex( 0 );
153 int count = 0;
154 for ( ListItem item : list )
155 {
156 model.add( count, item.getValue() );
157 if ( item.isSelected() )
158 {
159 selectField.setSelectedIndex( count );
160 }
161
162 ++count;
163 }
164
165 selectField.setModel( model );
166 }
167
168 /**
169 * Update a <code>ListBox</code> UI component.
170 *
171 * @param listBox The ListBox UI component that is to be updated.
172 * @param list The updated list data to apply to the UI component.
173 */
174 protected void updateListBox( ListBox listBox,
175 List<ListItem> list )
176 {
177 DefaultListModel model = new DefaultListModel();
178 int count = 0;
179 ArrayList<Integer> indices = new ArrayList<Integer>();
180
181 for ( ListItem item : list )
182 {
183 model.add( count, item.getValue() );
184 if ( item.isSelected() )
185 {
186 indices.add( count );
187 }
188 ++count;
189 }
190
191 listBox.setModel( model );
192
193 int[] selectedIndices = new int[ indices.size() ];
194 count = 0;
195 for ( int i : indices )
196 {
197 selectedIndices[ count++ ] = i;
198 }
199
200 listBox.setSelectedIndices( selectedIndices );
201 }
202 }