View Javadoc
1 /* 2 * Scope: a generic MVC framework. 3 * Copyright (c) 2000-2002, The Scope team 4 * All rights reserved. 5 * 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * Neither the name "Scope" nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR 27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 * 35 * 36 * $Id: ActiveBoundModel.java,v 1.12 2002/09/13 17:11:29 ludovicc Exp $ 37 */ 38 package org.scopemvc.view.util; 39 40 41 import org.apache.commons.logging.Log; 42 import org.apache.commons.logging.LogFactory; 43 import org.scopemvc.core.ModelChangeEvent; 44 import org.scopemvc.core.ModelChangeEventSource; 45 import org.scopemvc.core.ModelChangeListener; 46 import org.scopemvc.core.ModelChangeTypes; 47 import org.scopemvc.core.PropertyManager; 48 import org.scopemvc.core.Selector; 49 import org.scopemvc.util.Debug; 50 51 /*** 52 * <P> 53 * 54 * A {@link BoundModel} that handles ModelChangeEvents and provides full two-way 55 * data-binding between a View and its bound model property. The parent View 56 * needs to implement the {@link ModelBindable} interface to provide a generic 57 * interface used by this delegate. An ActiveBoundModel registers itself as a 58 * ModelChangeListener to the bound model object so that it can update its 59 * parent View. </P> 60 * 61 * @author <A HREF="mailto:smeyfroi@users.sourceforge.net">Steve Meyfroidt</A> 62 * @created 05 September 2002 63 * @version $Revision: 1.12 $ $Date: 2002/09/13 17:11:29 $ 64 * @see org.scopemvc.view.swing.SwingBoundModel 65 */ 66 public class ActiveBoundModel extends BoundModel implements ModelChangeListener { 67 68 private static final Log LOG = LogFactory.getLog(ActiveBoundModel.class); 69 70 /*** 71 * The ModelBindable View that delegates bound Model handling to this 72 * helper. 73 */ 74 protected ModelBindable view; 75 76 /*** 77 * PropertyManager for the bound model. 78 */ 79 protected PropertyManager manager; 80 81 82 /*** 83 * Constructor for the ActiveBoundModel object 84 * 85 * @param inView The view to bind to the model 86 */ 87 public ActiveBoundModel(ModelBindable inView) { 88 super(); 89 90 if (inView == null) { 91 throw new IllegalArgumentException("Can't create for null View."); 92 } 93 view = inView; 94 } 95 96 97 /*** 98 * Gets the property manager 99 * 100 * @return The propertyManager value 101 */ 102 public PropertyManager getPropertyManager() { 103 return manager; 104 } 105 106 107 // --------------------- Model to View ----------------------- 108 109 /*** 110 * Returns true if the property in the bound model is read only 111 * 112 * @return true if the property in the bound model is read only 113 */ 114 public boolean getPropertyReadOnly() { 115 boolean result = true; 116 if (boundModel != null) { 117 try { 118 if (Debug.ON) { 119 Debug.assertTrue(manager != null, "null manager"); 120 } 121 result = manager.isReadOnly(boundModel, getSelector()); 122 } catch (Exception e) { 123 // ignore and leave readOnly == true 124 } 125 } 126 return result; 127 } 128 129 130 /*** 131 * Gets the value of the property in the bound model 132 * 133 * @return The value of the property in the bound model 134 */ 135 public Object getPropertyValue() { 136 Object result = null; 137 if (boundModel != null) { 138 try { 139 if (Debug.ON) { 140 Debug.assertTrue(manager != null, "null manager"); 141 } 142 result = manager.get(boundModel, getSelector()); 143 } catch (Exception e) { 144 // ignore and leave result == null 145 } 146 } 147 return result; 148 } 149 150 151 /*** 152 * Gets the class of the property in the bound model 153 * 154 * @return The class of the property in the bound model 155 */ 156 public Class getPropertyClass() { 157 Class result = null; 158 if (boundModel != null) { 159 try { 160 if (Debug.ON) { 161 Debug.assertTrue(manager != null, "null manager"); 162 } 163 result = manager.getPropertyClass(boundModel, getSelector()); 164 } catch (Exception e) { 165 // ignore and leave result == null 166 } 167 } 168 return result; 169 } 170 171 172 /*** 173 * Sets the bound model 174 * 175 * @param inModel The new boundModel value 176 */ 177 public final void setBoundModel(Object inModel) { 178 if (LOG.isDebugEnabled()) { 179 LOG.debug("setBoundModel: " + inModel); 180 } 181 182 if (boundModel instanceof ModelChangeEventSource) { 183 ((ModelChangeEventSource) boundModel).removeModelChangeListener(this); 184 } 185 186 manager = null; 187 if (inModel instanceof ModelChangeEventSource) { 188 ((ModelChangeEventSource) inModel).addModelChangeListener(this); 189 } 190 if (inModel != null) { 191 manager = PropertyManager.getInstance(inModel); 192 } 193 194 boundModel = inModel; 195 updateFromModel(ModelChangeTypes.VALUE_CHANGED); 196 } 197 198 199 /*** 200 * Sets the selector 201 * 202 * @param inSelector The new selector value 203 */ 204 public final void setSelector(Selector inSelector) { 205 if (LOG.isDebugEnabled()) { 206 LOG.debug("setSelector: " + inSelector); 207 } 208 209 super.setSelector(inSelector); 210 updateFromModel(ModelChangeTypes.VALUE_CHANGED); 211 } 212 213 214 /*** 215 * Update the parent View in response to the passed ModelChangeEvent, if the 216 * event reports that the property we are bound to has changed. 217 * 218 * @param inEvent The event describing the change in the model 219 */ 220 public final void modelChanged(ModelChangeEvent inEvent) { 221 if (Debug.ON) { 222 Debug.assertTrue(boundModel instanceof ModelChangeEventSource, "boundModel not a Model"); 223 } 224 if (LOG.isDebugEnabled()) { 225 LOG.debug("modelChanged: view: " + view + ", event: " + inEvent); 226 LOG.debug("modelChanged: property selector: " + getSelector() + ", event selector: " + inEvent.getSelector()); 227 } 228 229 // Event affects us if a Model changes somewhere at or above us in the hierarchy. 230 if (inEvent.getModel() == boundModel && (getSelector() == null || getSelector().startsWith(inEvent.getSelector()))) { 231 if (LOG.isDebugEnabled()) { 232 LOG.debug("modelChanged: for me!"); 233 } 234 updateFromModel(inEvent.getType()); 235 view.validationSuccess(); 236 } 237 } 238 239 240 // ---------------------- View to Model ---------------------- 241 242 /*** 243 * Put the current View contents into the bound model property. <br> 244 * Errors in getting the UI's new value into the model property are handled 245 * by calling back into the parent View's 246 * {org.scopemvc.view.util.ModelBindable#validationFailed} with the 247 * Exception. <br> 248 * On no errors, call the parent's {org.scopemvc.view.util.ModelBindable#validationSuccess} 249 */ 250 public void updateModel() { 251 try { 252 // If boundModel==null then we're not hooked up. 253 // If selector==null then the view is hooked directly to a top-level model in a model tree, 254 // ...in which case there's no way we could be updating that model. 255 if (boundModel == null || getSelector() == null) { 256 LOG.warn("updateModel: not bound"); 257 return; 258 } 259 260 Object currentValue = view.getViewValue(); 261 if (LOG.isDebugEnabled()) { 262 LOG.debug("updateModel: view: " + view + ", currentValue: " + currentValue); 263 } 264 265 if (Debug.ON) { 266 Debug.assertTrue(manager != null, "null manager"); 267 } 268 manager.set(boundModel, getSelector(), currentValue); 269 view.validationSuccess(); 270 } catch (Exception e) { 271 LOG.warn("updateModel: " + view, e); 272 view.validationFailed(e); 273 } 274 } 275 276 277 /*** 278 * Calls parent View's {org.scopemvc.view.util.ModelBindable#validationSuccess} 279 * to clear any previous validation failure. 280 * 281 * @param inEventType The type of the change event, one of the {@link 282 * org.scopemvc.core.ModelChangeTypes ModelChangeTypes} values 283 */ 284 public void updateFromModel(int inEventType) { 285 // Find the new property value 286 Object property = getPropertyValue(); 287 boolean readOnly = getPropertyReadOnly(); 288 if (LOG.isDebugEnabled()) { 289 LOG.debug("updateFromModel: view: " + view + ", eventType: " + inEventType + ", property: " + property + ", readOnly: " + readOnly); 290 } 291 292 // for ACCESS_CHANGED and VALUE_CHANGED ***** 293 view.updateFromProperty(property, readOnly); 294 } 295 }

This page was automatically generated by Maven