##### Coverage Report - org.apache.commons.scxml.io.SCXMLSerializer

Classes in this File | Line Coverage | Branch Coverage | Complexity
SCXMLSerializer |
65% |
70% |
| 4.166666666666667;4.167

1 |  |
     /*
2 |  |
      *
3 |  |
      *   Copyright 2006 The Apache Software Foundation.
4 |  |
      *
5 |  |
      *  Licensed under the Apache License, Version 2.0 (the "License");
6 |  |
      *  you may not use this file except in compliance with the License.
7 |  |
      *  You may obtain a copy of the License at
8 |  |
      *
9 |  |
      *      http://www.apache.org/licenses/LICENSE-2.0
10 |  |
      *
11 |  |
      *  Unless required by applicable law or agreed to in writing, software
12 |  |
      *  distributed under the License is distributed on an "AS IS" BASIS,
13 |  |
      *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 |  |
      *  See the License for the specific language governing permissions and
15 |  |
      *  limitations under the License.
16 |  |
      *
17 |  |
      */
18 |  |
     package org.apache.commons.scxml.io;
19 |  |
20 |  |
     import java.io.StringWriter;
21 |  |
     import java.util.Iterator;
22 |  |
     import java.util.List;
23 |  |
     import java.util.Map;
24 |  |
     import java.util.Properties;
25 |  |
     import java.util.Set;
26 |  |
27 |  |
     import javax.xml.transform.OutputKeys;
28 |  |
     import javax.xml.transform.Result;
29 |  |
     import javax.xml.transform.Source;
30 |  |
     import javax.xml.transform.Transformer;
31 |  |
     import javax.xml.transform.TransformerException;
32 |  |
     import javax.xml.transform.TransformerFactory;
33 |  |
     import javax.xml.transform.dom.DOMSource;
34 |  |
     import javax.xml.transform.stream.StreamResult;
35 |  |
36 |  |
     import org.apache.commons.logging.LogFactory;
37 |  |
     import org.apache.commons.scxml.SCXMLHelper;
38 |  |
     import org.apache.commons.scxml.model.Action;
39 |  |
     import org.apache.commons.scxml.model.Assign;
40 |  |
     import org.apache.commons.scxml.model.Cancel;
41 |  |
     import org.apache.commons.scxml.model.Data;
42 |  |
     import org.apache.commons.scxml.model.Datamodel;
43 |  |
     import org.apache.commons.scxml.model.Else;
44 |  |
     import org.apache.commons.scxml.model.ElseIf;
45 |  |
     import org.apache.commons.scxml.model.Exit;
46 |  |
     import org.apache.commons.scxml.model.ExternalContent;
47 |  |
     import org.apache.commons.scxml.model.Finalize;
48 |  |
     import org.apache.commons.scxml.model.History;
49 |  |
     import org.apache.commons.scxml.model.If;
50 |  |
     import org.apache.commons.scxml.model.Initial;
51 |  |
     import org.apache.commons.scxml.model.Invoke;
52 |  |
     import org.apache.commons.scxml.model.Log;
53 |  |
     import org.apache.commons.scxml.model.OnEntry;
54 |  |
     import org.apache.commons.scxml.model.OnExit;
55 |  |
     import org.apache.commons.scxml.model.Parallel;
56 |  |
     import org.apache.commons.scxml.model.SCXML;
57 |  |
     import org.apache.commons.scxml.model.Send;
58 |  |
     import org.apache.commons.scxml.model.State;
59 |  |
     import org.apache.commons.scxml.model.Transition;
60 |  |
     import org.apache.commons.scxml.model.TransitionTarget;
61 |  |
     import org.apache.commons.scxml.model.Var;
62 |  |
     import org.w3c.dom.Node;
63 |  |
64 |  |
     /**
65 |  |
      * Utility class for serializing the Commons SCXML Java object
66 |  |
      * model. Class uses the visitor pattern to trace through the
67 |  |
      * object heirarchy. Used primarily for testing, debugging and
68 |  |
      * visual verification.
69 |  |
      *
70 |  |
      */
71 |  |
     public class SCXMLSerializer {
72 |  |
73 |  |
         /** The indent to be used while serializing an SCXML object. */
74 |  |
         private static final String INDENT = " ";
75 |  |
         /** The JAXP transformer. */
76 | 1 |
         private static final Transformer XFORMER = getTransformer();
77 |  |
78 |  |
         /**
79 |  |
          * Serialize this SCXML object (primarily for debugging).
80 |  |
          *
81 |  |
          * @param scxml
82 |  |
          *            The SCXML to be serialized
83 |  |
          * @return String The serialized SCXML
84 |  |
          */
85 |  |
         public static String serialize(final SCXML scxml) {
86 | 4 |
             StringBuffer b =
87 |  |
                 new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n").
88 |  |
                     append("<scxml xmlns=\"").append(scxml.getXmlns()).
89 |  |
                     append("\" version=\"").append(scxml.getVersion()).
90 |  |
                     append("\" initialstate=\"").append(scxml.getInitialstate()).
91 |  |
                     append("\">\n");
92 | 4 |
             if (XFORMER == null) {
93 | 0 |
                 org.apache.commons.logging.Log log = LogFactory.
94 | 0 |
                     getLog(SCXMLSerializer.class);
95 | 0 |
                 log.warn("SCXMLSerializer: DOM serialization pertinent to"
96 |  |
                     + " the document will be skipped since a suitable"
97 |  |
                     + " JAXP Transformer could not be instantiated.");
98 |  |
             }
99 | 4 |
             Datamodel dm = scxml.getDatamodel();
100 | 4 |
             if (dm != null) {
101 | 0 |
                 serializeDatamodel(b, dm, INDENT);
102 |  |
             }
103 | 4 |
             Map s = scxml.getStates();
104 | 4 |
             Iterator i = s.keySet().iterator();
105 | 12 |
             while (i.hasNext()) {
106 | 8 |
                 serializeState(b, (State) s.get(i.next()), INDENT);
107 |  |
             }
108 | 4 |
             b.append("</scxml>\n");
109 | 4 |
             return b.toString();
110 |  |
         }
111 |  |
112 |  |
         /**
113 |  |
          * Serialize this State object.
114 |  |
          *
115 |  |
          * @param b The buffer to append the serialization to
116 |  |
          * @param s The State to serialize
117 |  |
          * @param indent The indent for this XML element
118 |  |
          */
119 |  |
         public static void serializeState(final StringBuffer b,
120 |  |
                 final State s, final String indent) {
121 | 29 |
             b.append(indent).append("<state");
122 | 29 |
             serializeTransitionTargetAttributes(b, s);
123 | 29 |
             boolean f = s.getIsFinal();
124 | 29 |
             if (f) {
125 | 1 |
                 b.append(" final=\"true\"");
126 |  |
             }
127 | 29 |
             b.append(">\n");
128 | 29 |
             Initial ini = s.getInitial();
129 | 29 |
             if (ini != null) {
130 | 8 |
                 serializeInitial(b, ini, indent + INDENT);
131 |  |
             }
132 | 29 |
             List h = s.getHistory();
133 | 29 |
             if (h != null) {
134 | 29 |
                 serializeHistory(b, h, indent + INDENT);
135 |  |
             }
136 | 29 |
             Datamodel dm = s.getDatamodel();
137 | 29 |
             if (dm != null) {
138 | 0 |
                 serializeDatamodel(b, dm, indent + INDENT);
139 |  |
             }
140 | 29 |
             serializeOnEntry(b, s, indent + INDENT);
141 | 29 |
             Map t = s.getTransitions();
142 | 29 |
             Iterator i = t.keySet().iterator();
143 | 51 |
             while (i.hasNext()) {
144 | 22 |
                 List et = (List) t.get(i.next());
145 | 44 |
                 for (int len = 0; len < et.size(); len++) {
146 | 22 |
                     serializeTransition(b, (Transition) et.get(len), indent
147 |  |
                         + INDENT);
148 |  |
                 }
149 |  |
             }
150 | 29 |
             Parallel p = s.getParallel();
151 | 29 |
             Invoke inv = s.getInvoke();
152 | 29 |
             if (p != null) {
153 | 2 |
                 serializeParallel(b, p, indent + INDENT);
154 | 27 |
             } else if (inv != null) {
155 | 0 |
                 serializeInvoke(b , inv, indent + INDENT);
156 |  |
             } else {
157 | 27 |
                 Map c = s.getChildren();
158 | 27 |
                 Iterator j = c.keySet().iterator();
159 | 43 |
                 while (j.hasNext()) {
160 | 16 |
                     State cs = (State) c.get(j.next());
161 | 16 |
                     serializeState(b, cs, indent + INDENT);
162 |  |
                 }
163 |  |
             }
164 | 29 |
             serializeOnExit(b, s, indent + INDENT);
165 | 29 |
             b.append(indent).append("</state>\n");
166 | 29 |
         }
167 |  |
168 |  |
         /**
169 |  |
          * Serialize this Parallel object.
170 |  |
          *
171 |  |
          * @param b The buffer to append the serialization to
172 |  |
          * @param p The Parallel to serialize
173 |  |
          * @param indent The indent for this XML element
174 |  |
          */
175 |  |
         public static void serializeParallel(final StringBuffer b,
176 |  |
                 final Parallel p, final String indent) {
177 | 2 |
             b.append(indent).append("<parallel");
178 | 2 |
             serializeTransitionTargetAttributes(b, p);
179 | 2 |
             b.append(">\n");
180 | 2 |
             serializeOnEntry(b, p, indent + INDENT);
181 | 2 |
             Set s = p.getStates();
182 | 2 |
             Iterator i = s.iterator();
183 | 7 |
             while (i.hasNext()) {
184 | 5 |
                 serializeState(b, (State) i.next(), indent + INDENT);
185 |  |
             }
186 | 2 |
             serializeOnExit(b, p, indent + INDENT);
187 | 2 |
             b.append(indent).append("</parallel>\n");
188 | 2 |
         }
189 |  |
190 |  |
         /**
191 |  |
          * Serialize this Invoke object.
192 |  |
          *
193 |  |
          * @param b The buffer to append the serialization to
194 |  |
          * @param i The Invoke to serialize
195 |  |
          * @param indent The indent for this XML element
196 |  |
          */
197 |  |
         public static void serializeInvoke(final StringBuffer b,
198 |  |
                 final Invoke i, final String indent) {
199 | 0 |
             b.append(indent).append("<invoke");
200 | 0 |
             String ttype = i.getTargettype();
201 | 0 |
             String src = i.getSrc();
202 | 0 |
             String srcexpr = i.getSrcexpr();
203 | 0 |
             if (ttype != null) {
204 | 0 |
                 b.append(" targettype=\"").append(ttype).append("\"");
205 |  |
             }
206 |  |
             // Prefer src
207 | 0 |
             if (src != null) {
208 | 0 |
                 b.append(" src=\"").append(src).append("\"");
209 | 0 |
             } else if (srcexpr != null) {
210 | 0 |
                 b.append(" srcexpr=\"").append(srcexpr).append("\"");
211 |  |
             }
212 | 0 |
             b.append(">\n");
213 | 0 |
             Map params = i.getParams();
214 | 0 |
             for (Iterator iter = params.entrySet().iterator(); iter.hasNext();) {
215 | 0 |
                 Map.Entry e = (Map.Entry) iter.next();
216 | 0 |
                 b.append(indent).append(INDENT).append("<param name=\"").
217 |  |
                     append(e.getKey()).append("\" expr=\"").
218 |  |
                     append(e.getValue()).append("\"/>\n");
219 |  |
             }
220 | 0 |
             Finalize f = i.getFinalize();
221 | 0 |
             if (f != null) {
222 | 0 |
                 b.append(indent).append(INDENT).append("<finalize>\n");
223 | 0 |
                 serializeActions(b, f.getActions(), indent + INDENT + INDENT);
224 | 0 |
                 b.append(indent).append(INDENT).append("</finalize>\n");
225 |  |
             }
226 | 0 |
             b.append(indent).append("</invoke>\n");
227 | 0 |
         }
228 |  |
229 |  |
         /**
230 |  |
          * Serialize this Initial object.
231 |  |
          *
232 |  |
          * @param b The buffer to append the serialization to
233 |  |
          * @param i The Initial to serialize
234 |  |
          * @param indent The indent for this XML element
235 |  |
          */
236 |  |
         public static void serializeInitial(final StringBuffer b, final Initial i,
237 |  |
                 final String indent) {
238 | 8 |
             b.append(indent).append("<initial");
239 | 8 |
             serializeTransitionTargetAttributes(b, i);
240 | 8 |
             b.append(">\n");
241 | 8 |
             serializeTransition(b, i.getTransition(), indent + INDENT);
242 | 8 |
             b.append(indent).append("</initial>\n");
243 | 8 |
         }
244 |  |
245 |  |
         /**
246 |  |
          * Serialize the History.
247 |  |
          *
248 |  |
          * @param b The buffer to append the serialization to
249 |  |
          * @param l The List of History objects to serialize
250 |  |
          * @param indent The indent for this XML element
251 |  |
          */
252 |  |
         public static void serializeHistory(final StringBuffer b, final List l,
253 |  |
                 final String indent) {
254 | 29 |
             if (l.size() > 0) {
255 | 0 |
                 for (int i = 0; i < l.size(); i++) {
256 | 0 |
                     History h = (History) l.get(i);
257 | 0 |
                     b.append(indent).append("<history");
258 | 0 |
                     serializeTransitionTargetAttributes(b, h);
259 | 0 |
                      if (h.isDeep()) {
260 | 0 |
                          b.append(" type=\"deep\"");
261 |  |
                      } else {
262 | 0 |
                          b.append(" type=\"shallow\"");
263 |  |
                      }
264 | 0 |
                     b.append(">\n");
265 | 0 |
                     serializeTransition(b, h.getTransition(), indent + INDENT);
266 | 0 |
                     b.append(indent).append("</history>\n");
267 |  |
                 }
268 |  |
             }
269 | 29 |
         }
270 |  |
271 |  |
         /**
272 |  |
          * Serialize this Transition object.
273 |  |
          *
274 |  |
          * @param b The buffer to append the serialization to
275 |  |
          * @param t The Transition to serialize
276 |  |
          * @param indent The indent for this XML element
277 |  |
          */
278 |  |
         public static void serializeTransition(final StringBuffer b,
279 |  |
                 final Transition t, final String indent) {
280 | 30 |
             b.append(indent).append("<transition event=\"").append(t.getEvent())
281 |  |
                 .append("\" cond=\"").append(t.getCond()).append("\">\n");
282 | 30 |
             boolean exit = serializeActions(b, t.getActions(), indent + INDENT);
283 | 30 |
             if (!exit) {
284 | 30 |
                 serializeTarget(b, t, indent + INDENT);
285 |  |
             }
286 | 30 |
             b.append(indent).append("</transition>\n");
287 | 30 |
         }
288 |  |
289 |  |
         /**
290 |  |
          * Serialize this Transition's Target.
291 |  |
          *
292 |  |
          *
293 |  |
          * @param b The buffer to append the serialization to
294 |  |
          * @param t The Transition whose Target needs to be serialized
295 |  |
          * @param indent The indent for this XML element
296 |  |
          */
297 |  |
         public static void serializeTarget(final StringBuffer b,
298 |  |
                 final Transition t, final String indent) {
299 | 30 |
             b.append(indent).append("<target");
300 | 30 |
             String n = t.getNext();
301 | 30 |
             if (n != null) {
302 | 30 |
                 b.append(" next=\"" + n + "\">\n");
303 |  |
             } else {
304 | 0 |
                 b.append(">\n");
305 | 0 |
                 if (t.getTarget() != null) {
306 |  |
                     // The inline transition target can only be a state
307 | 0 |
                     serializeState(b, (State) t.getTarget(), indent + INDENT);
308 |  |
                 }
309 |  |
             }
310 | 30 |
             b.append(indent).append("</target>\n");
311 | 30 |
         }
312 |  |
313 |  |
         /**
314 |  |
          * Serialize this Datamodel object.
315 |  |
          *
316 |  |
          * @param b The buffer to append the serialization to
317 |  |
          * @param dm The Datamodel to be serialized
318 |  |
          * @param indent The indent for this XML element
319 |  |
          */
320 |  |
         public static void serializeDatamodel(final StringBuffer b,
321 |  |
                 final Datamodel dm, final String indent) {
322 | 0 |
             List data = dm.getData();
323 | 0 |
             if (data != null && data.size() > 0) {
324 | 0 |
                 b.append(indent).append("<datamodel>\n");
325 | 0 |
                 if (XFORMER == null) {
326 | 0 |
                     b.append(indent).append(INDENT).
327 |  |
                         append("<!-- Body content was not serialized -->\n");
328 | 0 |
                     b.append(indent).append("</datamodel>\n");
329 | 0 |
                     return;
330 |  |
                 }
331 | 0 |
                 for (Iterator iter = data.iterator(); iter.hasNext();) {
332 | 0 |
                     Data datum = (Data) iter.next();
333 | 0 |
                     Node dataNode = datum.getNode();
334 | 0 |
                     if (dataNode != null) {
335 | 0 |
                         StringWriter out = new StringWriter();
336 |  |
                         try {
337 | 0 |
                             Source input = new DOMSource(dataNode);
338 | 0 |
                             Result output = new StreamResult(out);
339 | 0 |
                             XFORMER.transform(input, output);
340 | 0 |
                         } catch (TransformerException te) {
341 | 0 |
                             org.apache.commons.logging.Log log = LogFactory.
342 |  |
                                 getLog(SCXMLSerializer.class);
343 | 0 |
                             log.error(te.getMessage(), te);
344 | 0 |
                             b.append(indent).append(INDENT).
345 |  |
                                 append("<!-- Data content not serialized -->\n");
346 | 0 |
                         }
347 | 0 |
                         b.append(indent).append(INDENT).append(out.toString());
348 |  |
                     } else {
349 | 0 |
                         b.append(indent).append(INDENT).append("<data name=\"").
350 |  |
                             append(datum.getName()).append("\" expr=\"").
351 |  |
                             append(datum.getExpr()).append("\" />\n");
352 |  |
                     }
353 |  |
                 }
354 | 0 |
                 b.append(indent).append("</datamodel>\n");
355 |  |
             }
356 | 0 |
         }
357 |  |
358 |  |
         /**
359 |  |
          * Serialize this OnEntry object.
360 |  |
          *
361 |  |
          * @param b The buffer to append the serialization to
362 |  |
          * @param t The TransitionTarget whose OnEntry is to be serialized
363 |  |
          * @param indent The indent for this XML element
364 |  |
          */
365 |  |
         public static void serializeOnEntry(final StringBuffer b,
366 |  |
                 final TransitionTarget t, final String indent) {
367 | 33 |
             OnEntry e = t.getOnEntry();
368 | 33 |
             if (e != null && e.getActions().size() > 0) {
369 | 7 |
                 b.append(indent).append("<onentry>\n");
370 | 7 |
                 serializeActions(b, e.getActions(), indent + INDENT);
371 | 7 |
                 b.append(indent).append("</onentry>\n");
372 |  |
             }
373 | 33 |
         }
374 |  |
375 |  |
         /**
376 |  |
          * Serialize this OnExit object.
377 |  |
          *
378 |  |
          * @param b The buffer to append the serialization to
379 |  |
          * @param t The TransitionTarget whose OnExit is to be serialized
380 |  |
          * @param indent The indent for this XML element
381 |  |
          */
382 |  |
         public static void serializeOnExit(final StringBuffer b,
383 |  |
                 final TransitionTarget t, final String indent) {
384 | 33 |
             OnExit x = t.getOnExit();
385 | 33 |
             if (x != null && x.getActions().size() > 0) {
386 | 7 |
                 b.append(indent).append("<onexit>\n");
387 | 7 |
                 serializeActions(b, x.getActions(), indent + INDENT);
388 | 7 |
                 b.append(indent).append("</onexit>\n");
389 |  |
             }
390 | 33 |
         }
391 |  |
392 |  |
         /**
393 |  |
          * Serialize this List of actions.
394 |  |
          *
395 |  |
          * @param b The buffer to append the serialization to
396 |  |
          * @param l The List of actions to serialize
397 |  |
          * @param indent The indent for this XML element
398 |  |
          * @return boolean true if the list of actions contains an &lt;exit/&gt;
399 |  |
          */
400 |  |
         public static boolean serializeActions(final StringBuffer b, final List l,
401 |  |
                 final String indent) {
402 | 57 |
             if (l == null) {
403 | 1 |
                 return false;
404 |  |
             }
405 | 56 |
             boolean exit = false;
406 | 56 |
             Iterator i = l.iterator();
407 | 88 |
             while (i.hasNext()) {
408 | 32 |
                 Action a = (Action) i.next();
409 | 32 |
                 if (a instanceof Var) {
410 | 6 |
                     Var v = (Var) a;
411 | 6 |
                     b.append(indent).append("<var name=\"").append(v.getName())
412 |  |
                             .append("\" expr=\"").append(v.getExpr()).append(
413 |  |
                                     "\"/>\n");
414 | 26 |
                 } else if (a instanceof Assign) {
415 | 5 |
                     Assign asn = (Assign) a;
416 | 5 |
                     b.append(indent).append("<assign");
417 | 5 |
                     if (!SCXMLHelper.isStringEmpty(asn.getLocation())) {
418 | 0 |
                         b.append(" location=\"").append(asn.getLocation());
419 | 0 |
                         if (!SCXMLHelper.isStringEmpty(asn.getSrc())) {
420 | 0 |
                             b.append("\" src=\"").append(asn.getSrc());
421 |  |
                         } else {
422 | 0 |
                             b.append("\" expr=\"").append(asn.getExpr());
423 |  |
                         }
424 |  |
                     } else {
425 | 5 |
                         b.append(" name=\"").append(asn.getName()).
426 |  |
                             append("\" expr=\"").append(asn.getExpr());
427 |  |
                     }
428 | 5 |
                     b.append("\"/>\n");
429 | 21 |
                 } else if (a instanceof Send) {
430 | 0 |
                     serializeSend(b, (Send) a, indent);
431 | 21 |
                 } else if (a instanceof Cancel) {
432 | 1 |
                     Cancel c = (Cancel) a;
433 | 1 |
                     b.append(indent).append("<cancel sendid=\"")
434 |  |
                         .append(c.getSendid()).append("\"/>\n");
435 | 20 |
                 } else if (a instanceof Log) {
436 | 11 |
                     Log lg = (Log) a;
437 | 11 |
                     b.append(indent).append("<log expr=\"").append(lg.getExpr())
438 |  |
                             .append("\"/>\n");
439 | 9 |
                 } else if (a instanceof Exit) {
440 | 1 |
                     Exit e = (Exit) a;
441 | 1 |
                     b.append(indent).append("<exit");
442 | 1 |
                     String expr = e.getExpr();
443 | 1 |
                     String nl = e.getNamelist();
444 | 1 |
                     if (expr != null) {
445 | 1 |
                         b.append(" expr=\"" + expr + "\"");
446 |  |
                     }
447 | 1 |
                     if (nl != null) {
448 | 1 |
                         b.append(" namelist=\"" + nl + "\"");
449 |  |
                     }
450 | 1 |
                     b.append("/>\n");
451 | 1 |
                     exit = true;
452 | 8 |
                 } else if (a instanceof If) {
453 | 4 |
                     If iff = (If) a;
454 | 4 |
                     serializeIf(b, iff, indent);
455 | 4 |
                 } else if (a instanceof Else) {
456 | 3 |
                     b.append(indent).append("<else/>\n");
457 | 1 |
                 } else if (a instanceof ElseIf) {
458 | 1 |
                     ElseIf eif = (ElseIf) a;
459 | 1 |
                     b.append(indent).append("<elseif cond=\"")
460 |  |
                             .append(eif.getCond()).append("\" />\n");
461 |  |
                 }
462 |  |
             }
463 | 56 |
             return exit;
464 |  |
         }
465 |  |
466 |  |
         /**
467 |  |
          * Serialize this Send object.
468 |  |
          *
469 |  |
          * @param b The buffer to append the serialization to
470 |  |
          * @param send The Send object to serialize
471 |  |
          * @param indent The indent for this XML element
472 |  |
          */
473 |  |
         public static void serializeSend(final StringBuffer b,
474 |  |
                 final Send send, final String indent) {
475 | 1 |
             b.append(indent).append("<send sendid=\"")
476 |  |
                 .append(send.getSendid()).append("\" target=\"")
477 |  |
                 .append(send.getTarget()).append("\" targetType=\"")
478 |  |
                 .append(send.getTargettype()).append("\" namelist=\"")
479 |  |
                 .append(send.getNamelist()).append("\" delay=\"")
480 |  |
                 .append(send.getDelay()).append("\" events=\"")
481 |  |
                 .append(send.getEvent()).append("\" hints=\"")
482 |  |
                 .append(send.getHints()).append("\">\n")
483 |  |
                 .append(getBodyContent(send))
484 |  |
                 .append(indent).append("</send>\n");
485 | 1 |
         }
486 |  |
487 |  |
         /**
488 |  |
          * Return serialized body of <code>ExternalContent</code>.
489 |  |
          *
490 |  |
          * @param externalContent The model element containing the body content
491 |  |
          * @return String The serialized body content
492 |  |
          */
493 |  |
         public static final String getBodyContent(
494 |  |
                 final ExternalContent externalContent) {
495 | 1 |
             StringBuffer buf = new StringBuffer();
496 | 1 |
             List externalNodes = externalContent.getExternalNodes();
497 | 1 |
             if (externalNodes.size() > 0 && XFORMER == null) {
498 | 0 |
                 buf.append("<!-- Body content was not serialized -->\n");
499 | 0 |
                 return buf.toString();
500 |  |
             }
501 | 1 |
             for (int i = 0; i < externalNodes.size(); i++) {
502 | 0 |
                 Source input = new DOMSource((Node) externalNodes.get(i));
503 | 0 |
                 StringWriter out = new StringWriter();
504 | 0 |
                 Result output = new StreamResult(out);
505 |  |
                 try {
506 | 0 |
                     XFORMER.transform(input, output);
507 | 0 |
                 } catch (TransformerException te) {
508 | 0 |
                     org.apache.commons.logging.Log log = LogFactory.
509 |  |
                         getLog(SCXMLSerializer.class);
510 | 0 |
                     log.error(te.getMessage(), te);
511 | 0 |
                     buf.append("<!-- Not all body content was serialized -->");
512 | 0 |
                 }
513 | 0 |
                 buf.append(out.toString()).append("\n");
514 |  |
             }
515 | 1 |
             return buf.toString();
516 |  |
         }
517 |  |
518 |  |
         /**
519 |  |
          * Serialize this If object.
520 |  |
          *
521 |  |
          * @param b The buffer to append the serialization to
522 |  |
          * @param iff The If object to serialize
523 |  |
          * @param indent The indent for this XML element
524 |  |
          */
525 |  |
         public static void serializeIf(final StringBuffer b,
526 |  |
                 final If iff, final String indent) {
527 | 4 |
             b.append(indent).append("<if cond=\"").append(iff.getCond()).append(
528 |  |
                     "\">\n");
529 | 4 |
             serializeActions(b, iff.getActions(), indent + INDENT);
530 | 4 |
             b.append(indent).append("</if>\n");
531 | 4 |
         }
532 |  |
533 |  |
         /**
534 |  |
          * Serialize properties of TransitionTarget which are element attributes.
535 |  |
          *
536 |  |
          * @param b The buffer to append the serialization to
537 |  |
          * @param t The TransitionTarget
538 |  |
          */
539 |  |
         private static void serializeTransitionTargetAttributes(
540 |  |
                 final StringBuffer b, final TransitionTarget t) {
541 | 39 |
             String id = t.getId();
542 | 39 |
             if (id != null) {
543 | 30 |
                 b.append(" id=\"").append(id).append("\"");
544 |  |
             }
545 | 39 |
             TransitionTarget pt = t.getParent();
546 | 39 |
             if (pt != null) {
547 | 31 |
                 String pid = pt.getId();
548 | 31 |
                 if (pid != null) {
549 | 31 |
                     b.append(" parentid=\"").append(pid).append("\"");
550 |  |
                 }
551 |  |
             }
552 | 39 |
         }
553 |  |
554 |  |
         /**
555 |  |
          * Get a <code>Transformer</code> instance.
556 |  |
          *
557 |  |
          * @return Transformer The <code>Transformer</code> instance.
558 |  |
          */
559 |  |
         private static Transformer getTransformer() {
560 | 1 |
             Transformer transformer = null;
561 | 1 |
             Properties outputProps = new Properties();
562 | 1 |
             outputProps.put(OutputKeys.OMIT_XML_DECLARATION, "yes");
563 | 1 |
             outputProps.put(OutputKeys.STANDALONE, "no");
564 | 1 |
             outputProps.put(OutputKeys.INDENT, "yes");
565 |  |
             try {
566 | 1 |
                 TransformerFactory tfFactory = TransformerFactory.newInstance();
567 | 1 |
                 transformer = tfFactory.newTransformer();
568 | 1 |
                 transformer.setOutputProperties(outputProps);
569 | 0 |
             } catch (Throwable t) {
570 | 0 |
                 return null;
571 | 1 |
             }
572 | 1 |
             return transformer;
573 |  |
         }
574 |  |
575 |  |
         /*
576 |  |
          * Private methods.
577 |  |
          */
578 |  |
         /**
579 |  |
          * Discourage instantiation since this is a utility class.
580 |  |
          */
581 |  |
         private SCXMLSerializer() {
582 | 0 |
             super();
583 | 0 |
         }
584 |  |
585 |  |
     }
586 |  |