View Javadoc
1 package xdoclet.sdk.xgg.binding; 2 3 import java.util.Collection; 4 import java.util.HashMap; 5 import java.util.HashSet; 6 import java.util.Iterator; 7 import java.util.Map; 8 import java.util.Set; 9 import java.util.Stack; 10 11 import org.relaxng.datatype.Datatype; 12 13 import com.sun.msv.grammar.AttributeExp; 14 import com.sun.msv.grammar.ChoiceExp; 15 import com.sun.msv.grammar.ConcurExp; 16 import com.sun.msv.grammar.DataExp; 17 import com.sun.msv.grammar.ElementExp; 18 import com.sun.msv.grammar.Expression; 19 import com.sun.msv.grammar.ExpressionPool; 20 import com.sun.msv.grammar.ExpressionVisitor; 21 import com.sun.msv.grammar.InterleaveExp; 22 import com.sun.msv.grammar.ListExp; 23 import com.sun.msv.grammar.MixedExp; 24 import com.sun.msv.grammar.NameClass; 25 import com.sun.msv.grammar.OneOrMoreExp; 26 import com.sun.msv.grammar.OtherExp; 27 import com.sun.msv.grammar.ReferenceExp; 28 import com.sun.msv.grammar.SequenceExp; 29 import com.sun.msv.grammar.ValueExp; 30 31 /*** 32 * This visitor visits a RNG grammar model and constructs an XGG model from it. 33 * The XGG model is simpler than the RNG model, and will be used to 34 * generate java beans representing the elements in the grammar. 35 * 36 * @author <a href="mailto:aslak.hellesoy at bekk.no">Aslak Hellesøy</a> 37 * @author <a href="mailto:christian at inx-soft.com">Christian Kvalheim</a> 38 * @author <a href="mailto:letiemble at users.sourceforge.net">Laurent Etiemble</a> 39 * @version $Revision: 1.7 $ 40 */ 41 class XGGVisitor implements ExpressionVisitor { 42 private final Stack _bindings = new Stack(); 43 private final HashMap _cardinalities = new HashMap(); 44 private final Map _elementMap = new HashMap(); 45 private final Stack _elements = new Stack(); 46 private final ExpressionPool _expressionPool; 47 48 /*** The current version */ 49 private final String _version; 50 /*** We're keeping track of already visited ElementExp to avoid infinite recursion. */ 51 private final Set _visitedElementExps = new HashSet(); 52 53 /*** 54 * Constructor for the XGGVisitor object 55 * 56 * @param expressionPool Description of the Parameter 57 * @param version Description of the Parameter 58 */ 59 public XGGVisitor(ExpressionPool expressionPool, String version) { 60 _expressionPool = expressionPool; 61 _version = version; 62 } 63 64 65 /*** 66 * Gets the elements attribute of the XGGVisitor object 67 * 68 * @return The elements value 69 */ 70 public Collection getElements() { 71 return _elementMap.values(); 72 } 73 74 75 /*** 76 * Description of the Method 77 * 78 * @return Description of the Return Value 79 */ 80 public Object onAnyString() { 81 // If a current binding is defined, set it up 82 if (!_bindings.isEmpty()) { 83 Binding binding = (Binding) _bindings.peek(); 84 binding.setRegexp(".*"); 85 } 86 87 return null; 88 } 89 90 91 /*** 92 * Description of the Method 93 * 94 * @param attributeExp Description of the Parameter 95 * @return Description of the Return Value 96 */ 97 public Object onAttribute(AttributeExp attributeExp) { 98 // Add the attribute to the current element 99 Element element = (Element) _elements.peek(); 100 101 // Create the Attribute binding 102 Attribute attribute = new Attribute(attributeExp.getNameClass().toString(), element); 103 element.addChild(attribute); 104 105 // Set the current binding 106 _bindings.push(attribute); 107 108 // Visit the content 109 Expression contentModel = attributeExp.getContentModel(); 110 contentModel.visit(this); 111 112 // Unset the current binding 113 _bindings.pop(); 114 115 // Set the cardinality 116 Cardinality card = (Cardinality) _cardinalities.get(element); 117 if (card != null) { 118 // If there is a cardinality context, set the minimum 119 attribute.getCardinality().setMin(card.getMin()); 120 } 121 122 return attribute; 123 } 124 125 126 /*** 127 * Description of the Method 128 * 129 * @param choiceExp Description of the Parameter 130 * @return Description of the Return Value 131 */ 132 public Object onChoice(ChoiceExp choiceExp) { 133 // Check if there is an element 134 Element element = null; 135 if (!_elements.isEmpty()) { 136 element = (Element) _elements.peek(); 137 } 138 139 // Check if there is a related cardinality 140 Cardinality card = (Cardinality) _cardinalities.get(element); 141 boolean started = (card == null); 142 if (started) { 143 card = new Cardinality(Cardinality.ZERO, Cardinality.ONE); 144 _cardinalities.put(element, card); 145 } 146 147 // Visit the children 148 for (Iterator children = choiceExp.children(); children.hasNext(); ) { 149 Expression child = (Expression) children.next(); 150 child.visit(this); 151 } 152 153 // If the cardinality was created here, then dispose it 154 if (started) { 155 _cardinalities.remove(element); 156 } 157 158 return null; 159 } 160 161 162 /*** 163 * Description of the Method 164 * 165 * @param concurExp Description of the Parameter 166 * @return Description of the Return Value 167 */ 168 public Object onConcur(ConcurExp concurExp) { 169 return null; 170 } 171 172 173 /*** 174 * Description of the Method 175 * 176 * @param dataExp Description of the Parameter 177 * @return Description of the Return Value 178 */ 179 public Object onData(DataExp dataExp) { 180 // Get the Data Type 181 Datatype dt = dataExp.getType(); 182 183 // If a current binding is defined, set it up 184 if (!_bindings.isEmpty()) { 185 Binding binding = (Binding) _bindings.peek(); 186 binding.setRegexp(DataTypeUtils.getRegexp(dt)); 187 } 188 189 return null; 190 } 191 192 193 /*** 194 * Description of the Method 195 * 196 * @param elementExp Description of the Parameter 197 * @return Description of the Return Value 198 */ 199 public Object onElement(ElementExp elementExp) { 200 // Create a new XGG Element 201 Element newElement = getElement(elementExp); 202 203 // Add the new element to the current one. 204 if (!_elements.isEmpty()) { 205 Element parent = (Element) _elements.peek(); 206 207 // Grab the cardinality associated to the parent 208 Cardinality card = (Cardinality) _cardinalities.get(parent); 209 210 // Seek if SubElement has already been registered 211 SubElement subElement = parent.getSubElement(newElement.getXmlName()); 212 boolean create = (subElement == null); 213 if (create) { 214 subElement = new SubElement(newElement, parent); 215 parent.addChild(subElement); 216 217 // If a cardinality exists, set the values 218 if (card != null) { 219 subElement.getCardinality().setMin(card.getMin()); 220 subElement.getCardinality().setMax(card.getMax()); 221 } 222 } else { 223 // If a cardinality dosen't exists, use the element one 224 if (card == null) { 225 subElement.getCardinality().setMin(subElement.getCardinality().getMin() + 1); 226 } else { 227 // If a cardinality exists... 228 if (card.getMax() != Cardinality.UNBOUNDED) { 229 // ... alter value 230 subElement.getCardinality().setMax(subElement.getCardinality().getMax() + card.getMax()); 231 } else { 232 // ... set value 233 subElement.getCardinality().setMax(Cardinality.UNBOUNDED); 234 } 235 } 236 } 237 // Normalize the cardinality 238 subElement.getCardinality().normalize(); 239 240 // Set and augment the index. 241 242 } 243 244 if (_visitedElementExps.add(elementExp)) { 245 _elements.push(newElement); 246 247 // Set the current binding 248 _bindings.push(newElement); 249 250 // Visit the content 251 Expression contentModel = elementExp.getContentModel(); 252 contentModel.visit(this); 253 254 // Unset the current binding 255 _bindings.pop(); 256 257 _elements.pop(); 258 } 259 260 return newElement; 261 } 262 263 264 /*** 265 * Description of the Method 266 * 267 * @return Description of the Return Value 268 */ 269 public Object onEpsilon() { 270 return null; 271 } 272 273 274 /*** 275 * Description of the Method 276 * 277 * @param interleaveExp Description of the Parameter 278 * @return Description of the Return Value 279 */ 280 public Object onInterleave(InterleaveExp interleaveExp) { 281 for (Iterator children = interleaveExp.children(); children.hasNext(); ) { 282 Expression child = (Expression) children.next(); 283 child.visit(this); 284 } 285 286 return null; 287 } 288 289 290 /*** 291 * Description of the Method 292 * 293 * @param listExp Description of the Parameter 294 * @return Description of the Return Value 295 */ 296 public Object onList(ListExp listExp) { 297 listExp.exp.visit(this); 298 299 return null; 300 } 301 302 303 /*** 304 * Description of the Method 305 * 306 * @param mixedExp Description of the Parameter 307 * @return Description of the Return Value 308 */ 309 public Object onMixed(MixedExp mixedExp) { 310 mixedExp.exp.visit(this); 311 312 return null; 313 } 314 315 316 /*** 317 * Description of the Method 318 * 319 * @return Description of the Return Value 320 */ 321 public Object onNullSet() { 322 return null; 323 } 324 325 326 /*** 327 * Description of the Method 328 * 329 * @param oneOrMoreExp Description of the Parameter 330 * @return Description of the Return Value 331 */ 332 public Object onOneOrMore(OneOrMoreExp oneOrMoreExp) { 333 // Check if there is an element 334 Element element = null; 335 if (!_elements.isEmpty()) { 336 element = (Element) _elements.peek(); 337 } 338 339 // Check if there is a related cardinality 340 Cardinality card = (Cardinality) _cardinalities.get(element); 341 boolean started = (card == null); 342 if (started) { 343 card = new Cardinality(Cardinality.ONE, Cardinality.UNBOUNDED); 344 _cardinalities.put(element, card); 345 } 346 card.setMax(Cardinality.UNBOUNDED); 347 348 // Visit the expression 349 oneOrMoreExp.exp.visit(this); 350 351 // If the cardinality was created here, then dispose it 352 if (started) { 353 _cardinalities.remove(element); 354 } 355 356 return null; 357 } 358 359 360 /*** 361 * Description of the Method 362 * 363 * @param otherExp Description of the Parameter 364 * @return Description of the Return Value 365 */ 366 public Object onOther(OtherExp otherExp) { 367 otherExp.exp.visit(this); 368 369 return null; 370 } 371 372 373 /*** 374 * Description of the Method 375 * 376 * @param referenceExp Description of the Parameter 377 * @return Description of the Return Value 378 */ 379 public Object onRef(ReferenceExp referenceExp) { 380 Expression expanded = referenceExp.getExpandedExp(_expressionPool); 381 expanded.visit(this); 382 383 return null; 384 } 385 386 387 /*** 388 * Description of the Method 389 * 390 * @param sequenceExp Description of the Parameter 391 * @return Description of the Return Value 392 */ 393 public Object onSequence(SequenceExp sequenceExp) { 394 for (Iterator children = sequenceExp.children(); children.hasNext(); ) { 395 Expression child = (Expression) children.next(); 396 child.visit(this); 397 } 398 399 return null; 400 } 401 402 403 /*** 404 * Description of the Method 405 * 406 * @param valueExp Description of the Parameter 407 * @return Description of the Return Value 408 */ 409 public Object onValue(ValueExp valueExp) { 410 // Get the Data Type 411 Datatype dt = valueExp.getType(); 412 413 // If a current binding is defined, set it up 414 if (!_bindings.isEmpty()) { 415 Binding binding = (Binding) _bindings.peek(); 416 binding.setRegexp(DataTypeUtils.getRegexp(dt)); 417 } 418 419 return null; 420 } 421 422 423 /*** 424 * Gets the element attribute of the XGGVisitor object 425 * 426 * @param elementExp Description of the Parameter 427 * @return The element value 428 */ 429 private Element getElement(ElementExp elementExp) { 430 // The xmlName is the same as in the DTD 431 NameClass nameClass = elementExp.getNameClass(); 432 String xmlName = nameClass.toString(); 433 434 Element result = (Element) _elementMap.get(xmlName); 435 if (result == null) { 436 result = new Element(xmlName, _version); 437 _elementMap.put(xmlName, result); 438 } 439 440 return result; 441 } 442 }

This page was automatically generated by Maven