Source Code Cross Referenced for SCXMLHelper.java in  » Library » Apache-commons-scxml-0.6-src » org » apache » commons » scxml » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Library » Apache commons scxml 0.6 src » org.apache.commons.scxml 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         *
009:         *     http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:        package org.apache.commons.scxml;
018:
019:        import java.util.HashSet;
020:        import java.util.IdentityHashMap;
021:        import java.util.Iterator;
022:        import java.util.List;
023:        import java.util.Map;
024:        import java.util.Set;
025:
026:        import org.apache.commons.logging.Log;
027:        import org.apache.commons.logging.LogFactory;
028:        import org.apache.commons.scxml.model.Data;
029:        import org.apache.commons.scxml.model.Datamodel;
030:        import org.apache.commons.scxml.model.Parallel;
031:        import org.apache.commons.scxml.model.Path;
032:        import org.apache.commons.scxml.model.State;
033:        import org.apache.commons.scxml.model.Transition;
034:        import org.apache.commons.scxml.model.TransitionTarget;
035:        import org.apache.commons.scxml.semantics.ErrorConstants;
036:        import org.w3c.dom.CharacterData;
037:        import org.w3c.dom.Node;
038:        import org.w3c.dom.Text;
039:
040:        /**
041:         * Helper class, all methods static final.
042:         *
043:         */
044:        public final class SCXMLHelper {
045:
046:            /**
047:             * Return true if the string is empty.
048:             *
049:             * @param attr The String to test
050:             * @return Is string empty
051:             */
052:            public static boolean isStringEmpty(final String attr) {
053:                if (attr == null || attr.trim().length() == 0) {
054:                    return true;
055:                }
056:                return false;
057:            }
058:
059:            /**
060:             * Checks whether a transition target tt (State or Parallel) is a
061:             * descendant of the transition target context.
062:             *
063:             * @param tt
064:             *            TransitionTarget to check - a potential descendant
065:             * @param ctx
066:             *            TransitionTarget context - a potential ancestor
067:             * @return true iff tt is a descendant of ctx, false otherwise
068:             */
069:            public static boolean isDescendant(final TransitionTarget tt,
070:                    final TransitionTarget ctx) {
071:                TransitionTarget parent = tt.getParent();
072:                while (parent != null) {
073:                    if (parent == ctx) {
074:                        return true;
075:                    }
076:                    parent = parent.getParent();
077:                }
078:                return false;
079:            }
080:
081:            /**
082:             * Creates a set which contains given states and all their ancestors
083:             * recursively up to the upper bound. Null upperBound means root
084:             * of the state machine.
085:             *
086:             * @param states The Set of States
087:             * @param upperBounds The Set of upper bound States
088:             * @return transitive closure of a given state set
089:             */
090:            public static Set getAncestorClosure(final Set states,
091:                    final Set upperBounds) {
092:                Set closure = new HashSet(states.size() * 2);
093:                for (Iterator i = states.iterator(); i.hasNext();) {
094:                    TransitionTarget tt = (TransitionTarget) i.next();
095:                    while (tt != null) {
096:                        if (!closure.add(tt)) {
097:                            //tt is already a part of the closure
098:                            break;
099:                        }
100:                        if (upperBounds != null && upperBounds.contains(tt)) {
101:                            break;
102:                        }
103:                        tt = tt.getParent();
104:                    }
105:                }
106:                return closure;
107:            }
108:
109:            /**
110:             * Checks whether a given set of states is a legal Harel State Table
111:             * configuration (with the respect to the definition of the OR and AND
112:             * states).
113:             *
114:             * @param states
115:             *            a set of states
116:             * @param errRep
117:             *            ErrorReporter to report detailed error info if needed
118:             * @return true if a given state configuration is legal, false otherwise
119:             */
120:            public static boolean isLegalConfig(final Set states,
121:                    final ErrorReporter errRep) {
122:                /*
123:                 * For every active state we add 1 to the count of its parent. Each
124:                 * Parallel should reach count equal to the number of its children and
125:                 * contribute by 1 to its parent. Each State should reach count exactly
126:                 * 1. SCXML elemnt (top) should reach count exactly 1. We essentially
127:                 * summarize up the hierarchy tree starting with a given set of
128:                 * states = active configuration.
129:                 */
130:                boolean legalConfig = true; // let's be optimists
131:                Map counts = new IdentityHashMap();
132:                Set scxmlCount = new HashSet();
133:                for (Iterator i = states.iterator(); i.hasNext();) {
134:                    TransitionTarget tt = (TransitionTarget) i.next();
135:                    TransitionTarget parent = null;
136:                    while ((parent = tt.getParent()) != null) {
137:                        HashSet cnt = (HashSet) counts.get(parent);
138:                        if (cnt == null) {
139:                            cnt = new HashSet();
140:                            counts.put(parent, cnt);
141:                        }
142:                        cnt.add(tt);
143:                        tt = parent;
144:                    }
145:                    //top-level contribution
146:                    scxmlCount.add(tt);
147:                }
148:                //Validate counts:
149:                for (Iterator i = counts.entrySet().iterator(); i.hasNext();) {
150:                    Map.Entry entry = (Map.Entry) i.next();
151:                    TransitionTarget tt = (TransitionTarget) entry.getKey();
152:                    Set count = (Set) entry.getValue();
153:                    if (tt instanceof  Parallel) {
154:                        Parallel p = (Parallel) tt;
155:                        if (count.size() < p.getStates().size()) {
156:                            errRep.onError(ErrorConstants.ILLEGAL_CONFIG,
157:                                    "Not all AND states active for parallel "
158:                                            + p.getId(), entry);
159:                            legalConfig = false;
160:                        }
161:                    } else {
162:                        if (count.size() > 1) {
163:                            errRep.onError(ErrorConstants.ILLEGAL_CONFIG,
164:                                    "Multiple OR states active for state "
165:                                            + tt.getId(), entry);
166:                            legalConfig = false;
167:                        }
168:                    }
169:                    count.clear(); //cleanup
170:                }
171:                if (scxmlCount.size() > 1) {
172:                    errRep.onError(ErrorConstants.ILLEGAL_CONFIG,
173:                            "Multiple top-level OR states active!", scxmlCount);
174:                }
175:                //cleanup
176:                scxmlCount.clear();
177:                counts.clear();
178:                return legalConfig;
179:            }
180:
181:            /**
182:             * Finds the least common ancestor of transition targets tt1 and tt2 if
183:             * one exists.
184:             *
185:             * @param tt1 First TransitionTarget
186:             * @param tt2 Second TransitionTarget
187:             * @return closest common ancestor of tt1 and tt2 or null
188:             */
189:            public static TransitionTarget getLCA(final TransitionTarget tt1,
190:                    final TransitionTarget tt2) {
191:                if (tt1 == tt2) {
192:                    return tt1; //self-transition
193:                } else if (isDescendant(tt1, tt2)) {
194:                    return tt2;
195:                } else if (isDescendant(tt2, tt1)) {
196:                    return tt1;
197:                }
198:                Set parents = new HashSet();
199:                TransitionTarget tmp = tt1;
200:                while ((tmp = tmp.getParent()) != null) {
201:                    if (tmp instanceof  State) {
202:                        parents.add(tmp);
203:                    }
204:                }
205:                tmp = tt2;
206:                while ((tmp = tmp.getParent()) != null) {
207:                    if (tmp instanceof  State) {
208:                        //test redundant add = common ancestor
209:                        if (!parents.add(tmp)) {
210:                            parents.clear();
211:                            return tmp;
212:                        }
213:                    }
214:                }
215:                return null;
216:            }
217:
218:            /**
219:             * Returns the set of all states (and parallels) which are exited if a
220:             * given transition t is going to be taken.
221:             * Current states are necessary to be taken into account
222:             * due to orthogonal states and cross-region transitions -
223:             * see UML specs for more details.
224:             *
225:             * @param t
226:             *            transition to be taken
227:             * @param currentStates
228:             *            the set of current states (simple states only)
229:             * @return a set of all states (including composite) which are exited if a
230:             *         given transition is taken
231:             */
232:            public static Set getStatesExited(final Transition t,
233:                    final Set currentStates) {
234:                Set allStates = new HashSet();
235:                Path p = t.getPath();
236:                //the easy part
237:                allStates.addAll(p.getUpwardSegment());
238:                TransitionTarget source = t.getParent();
239:                for (Iterator act = currentStates.iterator(); act.hasNext();) {
240:                    TransitionTarget a = (TransitionTarget) act.next();
241:                    if (isDescendant(a, source)) {
242:                        boolean added = false;
243:                        added = allStates.add(a);
244:                        while (added && a != source) {
245:                            a = a.getParent();
246:                            added = allStates.add(a);
247:                        }
248:                    }
249:                }
250:                if (p.isCrossRegion()) {
251:                    for (Iterator regions = p.getRegionsExited().iterator(); regions
252:                            .hasNext();) {
253:                        Parallel par = ((Parallel) ((State) regions.next())
254:                                .getParent());
255:                        //let's find affected states in sibling regions
256:                        for (Iterator siblings = par.getStates().iterator(); siblings
257:                                .hasNext();) {
258:                            State s = (State) siblings.next();
259:                            for (Iterator act = currentStates.iterator(); act
260:                                    .hasNext();) {
261:                                TransitionTarget a = (TransitionTarget) act
262:                                        .next();
263:                                if (isDescendant(a, s)) {
264:                                    //a is affected
265:                                    boolean added = false;
266:                                    added = allStates.add(a);
267:                                    while (added && a != s) {
268:                                        a = a.getParent();
269:                                        added = allStates.add(a);
270:                                    }
271:                                }
272:                            }
273:                        }
274:                    }
275:                }
276:                return allStates;
277:            }
278:
279:            /**
280:             * According to the UML definition, two transitions
281:             * are conflicting if the sets of states they exit overlap.
282:             *
283:             * @param t1 a transition to check against t2
284:             * @param t2 a transition to check against t1
285:             * @param currentStates the set of current states (simple states only)
286:             * @return true if the t1 and t2 are conflicting transitions
287:             * @see #getStatesExited(Transition, Set)
288:             */
289:            public static boolean inConflict(final Transition t1,
290:                    final Transition t2, final Set currentStates) {
291:                Set ts1 = getStatesExited(t1, currentStates);
292:                Set ts2 = getStatesExited(t2, currentStates);
293:                ts1.retainAll(ts2);
294:                if (ts1.isEmpty()) {
295:                    return false;
296:                }
297:                return true;
298:            }
299:
300:            /**
301:             * Whether the first argument is a subtype of the second.
302:             *
303:             * @param child The candidate subtype
304:             * @param parent The supertype
305:             * @return true if child is subtype of parent, otherwise false
306:             */
307:            public static boolean subtypeOf(final Class child,
308:                    final Class parent) {
309:                if (child == null || parent == null) {
310:                    return false;
311:                }
312:                for (Class current = child; current != Object.class; current = current
313:                        .getSuperclass()) {
314:                    if (current == parent) {
315:                        return true;
316:                    }
317:                }
318:                return false;
319:            }
320:
321:            /**
322:             * Whether the class implements the interface.
323:             *
324:             * @param clas The candidate class
325:             * @param interfayce The interface
326:             * @return true if clas implements interfayce, otherwise false
327:             */
328:            public static boolean implementationOf(final Class clas,
329:                    final Class interfayce) {
330:                if (clas == null || interfayce == null
331:                        || !interfayce.isInterface()) {
332:                    return false;
333:                }
334:                for (Class current = clas; current != Object.class; current = current
335:                        .getSuperclass()) {
336:                    Class[] implementedInterfaces = current.getInterfaces();
337:                    for (int i = 0; i < implementedInterfaces.length; i++) {
338:                        if (implementedInterfaces[i] == interfayce) {
339:                            return true;
340:                        }
341:                    }
342:                }
343:                return false;
344:            }
345:
346:            /**
347:             * Set node value, depending on its type, from a String.
348:             *
349:             * @param node A Node whose value is to be set
350:             * @param value The new value
351:             */
352:            public static void setNodeValue(final Node node, final String value) {
353:                switch (node.getNodeType()) {
354:                case Node.ATTRIBUTE_NODE:
355:                    node.setNodeValue(value);
356:                    break;
357:                case Node.ELEMENT_NODE:
358:                    //remove all text children
359:                    if (node.hasChildNodes()) {
360:                        Node child = node.getFirstChild();
361:                        while (child != null) {
362:                            if (child.getNodeType() == Node.TEXT_NODE) {
363:                                node.removeChild(child);
364:                            }
365:                            child = child.getNextSibling();
366:                        }
367:                    }
368:                    //create a new text node and append
369:                    Text txt = node.getOwnerDocument().createTextNode(value);
370:                    node.appendChild(txt);
371:                    break;
372:                case Node.TEXT_NODE:
373:                case Node.CDATA_SECTION_NODE:
374:                    ((CharacterData) node).setData(value);
375:                    break;
376:                default:
377:                    String err = "Trying to set value of a strange Node type: "
378:                            + node.getNodeType();
379:                    //Logger.logln(Logger.E, err);
380:                    throw new IllegalArgumentException(err);
381:                }
382:            }
383:
384:            /**
385:             * Retrieve a DOM node value as a string depending on its type.
386:             *
387:             * @param node A node to be retreived
388:             * @return The value as a string
389:             */
390:            public static String getNodeValue(final Node node) {
391:                String result = "";
392:                if (node == null) {
393:                    return result;
394:                }
395:                switch (node.getNodeType()) {
396:                case Node.ATTRIBUTE_NODE:
397:                    result = node.getNodeValue();
398:                    break;
399:                case Node.ELEMENT_NODE:
400:                    if (node.hasChildNodes()) {
401:                        Node child = node.getFirstChild();
402:                        StringBuffer buf = new StringBuffer();
403:                        while (child != null) {
404:                            if (child.getNodeType() == Node.TEXT_NODE) {
405:                                buf.append(((CharacterData) child).getData());
406:                            }
407:                            child = child.getNextSibling();
408:                        }
409:                        result = buf.toString();
410:                    }
411:                    break;
412:                case Node.TEXT_NODE:
413:                case Node.CDATA_SECTION_NODE:
414:                    result = ((CharacterData) node).getData();
415:                    break;
416:                default:
417:                    String err = "Trying to get value of a strange Node type: "
418:                            + node.getNodeType();
419:                    //Logger.logln(Logger.W, err );
420:                    throw new IllegalArgumentException(err);
421:                }
422:                return result.trim();
423:            }
424:
425:            /**
426:             * Clone data model.
427:             *
428:             * @param ctx The context to clone to.
429:             * @param datamodel The datamodel to clone.
430:             * @param evaluator The expression evaluator.
431:             * @param log The error log.
432:             */
433:            public static void cloneDatamodel(final Datamodel datamodel,
434:                    final Context ctx, final Evaluator evaluator, final Log log) {
435:                if (datamodel == null) {
436:                    return;
437:                }
438:                List data = datamodel.getData();
439:                if (data == null) {
440:                    return;
441:                }
442:                for (Iterator iter = data.iterator(); iter.hasNext();) {
443:                    Data datum = (Data) iter.next();
444:                    Node datumNode = datum.getNode();
445:                    Node valueNode = null;
446:                    if (datumNode != null) {
447:                        valueNode = datumNode.cloneNode(true);
448:                    }
449:                    // prefer "src" over "expr" over "inline"
450:                    if (!SCXMLHelper.isStringEmpty(datum.getSrc())) {
451:                        ctx.setLocal(datum.getName(), valueNode);
452:                    } else if (!SCXMLHelper.isStringEmpty(datum.getExpr())) {
453:                        Object value = null;
454:                        try {
455:                            ctx.setLocal(NAMESPACES_KEY, datum.getNamespaces());
456:                            value = evaluator.eval(ctx, datum.getExpr());
457:                            ctx.setLocal(NAMESPACES_KEY, null);
458:                        } catch (SCXMLExpressionException see) {
459:                            if (log != null) {
460:                                log.error(see.getMessage(), see);
461:                            } else {
462:                                Log defaultLog = LogFactory
463:                                        .getLog(SCXMLHelper.class);
464:                                defaultLog.error(see.getMessage(), see);
465:                            }
466:                        }
467:                        ctx.setLocal(datum.getName(), value);
468:                    } else {
469:                        ctx.setLocal(datum.getName(), valueNode);
470:                    }
471:                }
472:            }
473:
474:            /**
475:             * Discourage instantiation since this is a utility class.
476:             */
477:            private SCXMLHelper() {
478:                super ();
479:            }
480:
481:            /**
482:             * Current document namespaces are saved under this key in the parent
483:             * state's context.
484:             */
485:            private static final String NAMESPACES_KEY = "_ALL_NAMESPACES";
486:
487:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.