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: ModelToXML.java,v 1.7 2002/09/05 15:41:45 ludovicc Exp $ 37 */ 38 package org.scopemvc.view.servlet.xml; 39 40 41 import java.util.HashMap; 42 import java.util.Iterator; 43 import org.apache.commons.logging.Log; 44 import org.apache.commons.logging.LogFactory; 45 import org.scopemvc.core.IntIndexSelector; 46 import org.scopemvc.core.PropertyManager; 47 import org.scopemvc.core.Selector; 48 import org.scopemvc.model.collection.ArrayModel; 49 import org.scopemvc.model.collection.ListModel; 50 import org.scopemvc.util.Debug; 51 import org.scopemvc.util.convertor.StringConvertor; 52 import org.scopemvc.util.convertor.StringConvertors; 53 import org.xml.sax.Attributes; 54 import org.xml.sax.ContentHandler; 55 import org.xml.sax.helpers.AttributesImpl; 56 57 /*** 58 * <P> 59 * 60 * Converts a model into an XML document (as SAX events driving a 61 * ContentHandler). Uses a {@link PropertyIDGenerator} to create "path" 62 * attributes for all elements, and "id" attributes for model elements. </P> <P> 63 * 64 * Handles circular references using the "ID" and "IDREF" pattern. </P> <P> 65 * 66 * <PRE> 67 * (data id='_root') 68 * (name path='name')Steve(/name) 69 * (pets path='pets') 70 * (element index='0' path='pets.0') 71 * (data id='pets.0') 72 * (name path='pets.0.name')Trevor(/name) 73 * (/data) 74 * (/element) 75 * (/pets) 76 * (/data) 77 * </PRE> </P> 78 * 79 * @author <A HREF="mailto:smeyfroi@users.sourceforge.net">Steve Meyfroidt</A> 80 * @created 05 September 2002 81 * @version $Revision: 1.7 $ $Date: 2002/09/05 15:41:45 $ 82 */ 83 public class ModelToXML { 84 85 // Some constants for creating the XML 86 /*** 87 * TODO: describe of the Field 88 */ 89 protected final static String ID_ATTRIBUTE = "id"; 90 /*** 91 * TODO: describe of the Field 92 */ 93 protected final static String IDREF_ATTRIBUTE = "idref"; 94 /*** 95 * TODO: describe of the Field 96 */ 97 protected final static String CDATA_TYPE = "CDATA"; 98 /*** 99 * TODO: describe of the Field 100 */ 101 protected final static String PATH_ATTRIBUTE = "id"; 102 /*** 103 * TODO: describe of the Field 104 */ 105 protected final static Attributes EMPTY_ATTRIBUTES = new AttributesImpl(); 106 107 /*** 108 * Element to contain contents of a collection model. 109 */ 110 protected static String COLLECTION_ELEMENT = "element"; 111 112 /*** 113 * Attribute to index the contents of a collection model. 114 */ 115 protected static String COLLECTION_INDEX_ATTRIBUTE = "index"; 116 117 /*** 118 * Element to contain a model object. 119 */ 120 protected static String MODEL_ELEMENT = "data"; 121 122 private final static Log LOG = LogFactory.getLog(ModelToXML.class); 123 124 // Reuse these Attributes to avoid object creation (initialised in init()). 125 /*** 126 * TODO: describe of the Field 127 */ 128 protected AttributesImpl idAttributes; 129 /*** 130 * TODO: describe of the Field 131 */ 132 protected AttributesImpl idrefAttributes; 133 /*** 134 * TODO: describe of the Field 135 */ 136 protected AttributesImpl pathIndexAttributes; 137 /*** 138 * TODO: describe of the Field 139 */ 140 protected AttributesImpl indexAttributes; 141 /*** 142 * TODO: describe of the Field 143 */ 144 protected AttributesImpl pathAttributes; 145 146 147 /*** 148 * Constructor for the ModelToXML object 149 */ 150 public ModelToXML() { 151 init(); 152 } 153 154 155 /*** 156 * @param inContentHandler Drive this ContentHandler with the Model's SAX 157 * events. 158 * @param inModel Model object to write. null generates no SAX. 159 * @param inIDGenerator TODO: Describe the Parameter 160 * @throws Exception TODO: Describe the Exception 161 */ 162 public void modelToXML(Object inModel, ContentHandler inContentHandler, PropertyIDGenerator inIDGenerator) 163 throws Exception { 164 165 inContentHandler.startDocument(); 166 167 IdRefMap idRefMap = new IdRefMap(); 168 String id = idRefMap.getNextId(); 169 idAttributes.setValue(0, id); 170 idRefMap.storeModel(id, inModel); 171 172 inContentHandler.startElement("", MODEL_ELEMENT, MODEL_ELEMENT, idAttributes); 173 174 propertiesToXML(inModel, inContentHandler, inIDGenerator, idRefMap); 175 176 inContentHandler.endElement("", MODEL_ELEMENT, MODEL_ELEMENT); 177 178 inContentHandler.endDocument(); 179 } 180 181 182 /*** 183 * Initialise the Attributes that are reused during SAX generation. 184 */ 185 protected void init() { 186 idAttributes = new AttributesImpl(); 187 idAttributes.addAttribute("", ID_ATTRIBUTE, ID_ATTRIBUTE, CDATA_TYPE, ""); 188 189 idrefAttributes = new AttributesImpl(); 190 idrefAttributes.addAttribute("", IDREF_ATTRIBUTE, IDREF_ATTRIBUTE, CDATA_TYPE, ""); 191 192 pathIndexAttributes = new AttributesImpl(); 193 pathIndexAttributes.addAttribute("", PATH_ATTRIBUTE, PATH_ATTRIBUTE, CDATA_TYPE, ""); 194 pathIndexAttributes.addAttribute("", COLLECTION_INDEX_ATTRIBUTE, COLLECTION_INDEX_ATTRIBUTE, CDATA_TYPE, ""); 195 196 indexAttributes = new AttributesImpl(); 197 indexAttributes.addAttribute("", COLLECTION_INDEX_ATTRIBUTE, COLLECTION_INDEX_ATTRIBUTE, CDATA_TYPE, ""); 198 199 pathAttributes = new AttributesImpl(); 200 pathAttributes.addAttribute("", PATH_ATTRIBUTE, PATH_ATTRIBUTE, CDATA_TYPE, ""); 201 } 202 203 204 /*** 205 * TODO: document the method 206 * 207 * @param inModel TODO: Describe the Parameter 208 * @param inContentHandler TODO: Describe the Parameter 209 * @param inIDGenerator TODO: Describe the Parameter 210 * @param inIdRefMap TODO: Describe the Parameter 211 * @throws Exception TODO: Describe the Exception 212 */ 213 protected void propertiesToXML(Object inModel, ContentHandler inContentHandler, PropertyIDGenerator inIDGenerator, IdRefMap inIdRefMap) 214 throws Exception { 215 if (Debug.ON) { 216 Debug.assertTrue(inContentHandler != null, "null ContentHandler"); 217 } 218 if (LOG.isDebugEnabled()) { 219 LOG.debug("propertiesToXML: idGenerator=" + inIDGenerator); 220 } 221 222 // Don't serialise null models 223 if (inModel == null) { 224 return; 225 } 226 227 // Get a PropertyManager for the model 228 PropertyManager manager = PropertyManager.getInstance(inModel); 229 if (Debug.ON) { 230 Debug.assertTrue(manager != null, "null manager"); 231 } 232 233 // Serialise the properties using a SelectorIterator 234 Iterator i = manager.getSelectorIterator(inModel); 235 if (Debug.ON) { 236 Debug.assertTrue(i != null, "null Iterator"); 237 } 238 while (i.hasNext()) { 239 240 try { 241 // selector 242 Object o = i.next(); 243 if (Debug.ON) { 244 Debug.assertTrue(o instanceof Selector, "not a Selector: " + o); 245 } 246 Selector selector = (Selector) o; 247 Object property = manager.get(inModel, selector); 248 249 // Don't serialise null properties 250 if (property == null) { 251 continue; 252 } 253 254 // Don't serialise the array property of an ArrayModel ***** feels like a hack 255 if (inModel instanceof ArrayModel && ArrayModel.ARRAY.equals(selector)) { 256 continue; 257 } 258 259 // Don't serialise the list property of a ListModel ***** feels like a hack 260 if (inModel instanceof ListModel && ListModel.LIST.equals(selector)) { 261 continue; 262 } 263 264 StringConvertor convertor = StringConvertors.forClass(property.getClass()); 265 inIDGenerator.startProperty(selector); 266 String path = inIDGenerator.getPropertyID(); 267 268 // If selector is an IntIndexSelector then write the 269 // ... property like: <element index='0' path='xxx'> 270 // ... else write it like: <{selectorName} path='xxx'> 271 if (selector instanceof IntIndexSelector) { 272 if (path != null) { 273 pathIndexAttributes.setValue(0, path); 274 pathIndexAttributes.setValue(1, selector.getName()); 275 inContentHandler.startElement("", COLLECTION_ELEMENT, COLLECTION_ELEMENT, pathIndexAttributes); 276 } else { 277 indexAttributes.setValue(0, selector.getName()); 278 inContentHandler.startElement("", COLLECTION_ELEMENT, COLLECTION_ELEMENT, indexAttributes); 279 } 280 } else { 281 if (path != null) { 282 pathAttributes.setValue(0, path); 283 inContentHandler.startElement("", selector.getName(), selector.getName(), pathAttributes); 284 } else { 285 inContentHandler.startElement("", selector.getName(), selector.getName(), EMPTY_ATTRIBUTES); 286 } 287 } 288 289 // value, using StringConvertor 290 if (convertor != null) { 291 String value = convertor.valueAsString(property); 292 if (Debug.ON) { 293 Debug.assertTrue(value != null); 294 } 295 char[] valueElement = value.toCharArray(); 296 inContentHandler.characters(valueElement, 0, valueElement.length); 297 } else { 298 // A Model so check if already serialised (look in the IdRefMap) 299 String previousId = inIdRefMap.findIdFor(property); 300 if (previousId != null) { 301 idrefAttributes.setValue(0, previousId); 302 inContentHandler.startElement("", MODEL_ELEMENT, MODEL_ELEMENT, idrefAttributes); 303 } else { 304 // ... if not previously serialised then do it here 305 String id = inIdRefMap.getNextId(); 306 idAttributes.setValue(0, id); 307 inContentHandler.startElement("", MODEL_ELEMENT, MODEL_ELEMENT, idAttributes); 308 inIdRefMap.storeModel(id, property); 309 propertiesToXML(property, inContentHandler, inIDGenerator, inIdRefMap); 310 } 311 inContentHandler.endElement("", MODEL_ELEMENT, MODEL_ELEMENT); 312 } 313 314 // end of property 315 if (selector instanceof IntIndexSelector) { 316 inContentHandler.endElement("", COLLECTION_ELEMENT, COLLECTION_ELEMENT); 317 } else { 318 inContentHandler.endElement("", selector.getName(), selector.getName()); 319 } 320 321 inIDGenerator.endProperty(); 322 323 } catch (Exception e) { 324 // ignore: may not be able to get write-only properties 325 } 326 } 327 } 328 } 329 330 class IdRefMap { 331 332 private long nextId = 0; 333 private HashMap models = new HashMap(); 334 335 /*** 336 * Gets the next id 337 * 338 * @return The nextId value 339 */ 340 String getNextId() { 341 String result = "_" + Long.toString(nextId); 342 nextId++; 343 return result; 344 } 345 346 /*** 347 * TODO: document the method 348 * 349 * @param inModel TODO: Describe the Parameter 350 * @return TODO: Describe the Return Value 351 */ 352 String findIdFor(Object inModel) { 353 return (String) models.get(inModel); 354 } 355 356 /*** 357 * TODO: document the method 358 * 359 * @param inId TODO: Describe the Parameter 360 * @param inModel TODO: Describe the Parameter 361 */ 362 void storeModel(String inId, Object inModel) { 363 models.put(inModel, inId); 364 } 365 }

This page was automatically generated by Maven