Source Code Cross Referenced for CalloutEmitter.java in  » Database-DBMS » Ozone-1.1 » com » nwalsh » saxon » 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 » Database DBMS » Ozone 1.1 » com.nwalsh.saxon 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package com.nwalsh.saxon;
002:
003:        import java.util.Stack;
004:        import java.util.StringTokenizer;
005:        import org.xml.sax.*;
006:        import org.w3c.dom.*;
007:        import javax.xml.transform.TransformerException;
008:        import com.icl.saxon.Controller;
009:        import com.icl.saxon.om.NamePool;
010:        import com.icl.saxon.output.Emitter;
011:        import com.icl.saxon.tree.AttributeCollection;
012:
013:        /**
014:         * <p>Saxon extension to decorate a result tree fragment with callouts.</p>
015:         *
016:         * <p>$Id: CalloutEmitter.java,v 1.1 2001/07/16 21:23:57 nwalsh Exp $</p>
017:         *
018:         * <p>Copyright (C) 2000 Norman Walsh.</p>
019:         *
020:         * <p>This class provides the guts of a
021:         * <a href="http://users.iclway.co.uk/mhkay/saxon/">Saxon 6.*</a>
022:         * implementation of callouts for verbatim environments. (It is used
023:         * by the Verbatim class.)</p>
024:         *
025:         * <p>The general design is this: the stylesheets construct a result tree
026:         * fragment for some verbatim environment. The Verbatim class initializes
027:         * a CalloutEmitter with information about the callouts that should be applied
028:         * to the verbatim environment in question. Then the result tree fragment
029:         * is "replayed" through the CalloutEmitter; the CalloutEmitter builds a
030:         * new result tree fragment from this event stream, decorated with callouts,
031:         * and that is returned.</p>
032:         *
033:         * <p><b>Change Log:</b></p>
034:         * <dl>
035:         * <dt>1.0</dt>
036:         * <dd><p>Initial release.</p></dd>
037:         * </dl>
038:         *
039:         * @see Verbatim
040:         *
041:         * @author Norman Walsh
042:         * <a href="mailto:ndw@nwalsh.com">ndw@nwalsh.com</a>
043:         *
044:         * @version $Id: CalloutEmitter.java,v 1.1 2001/07/16 21:23:57 nwalsh Exp $
045:         *
046:         */
047:        public class CalloutEmitter extends CopyEmitter {
048:            /** A stack for the preserving information about open elements. */
049:            protected Stack elementStack = null;
050:
051:            /** A stack for holding information about temporarily closed elements. */
052:            protected Stack tempStack = null;
053:
054:            /** Is the next element absolutely the first element in the fragment? */
055:            protected boolean firstElement = false;
056:
057:            /** The FO namespace name. */
058:            protected static String foURI = "http://www.w3.org/1999/XSL/Format";
059:
060:            /** The default column for callouts that specify only a line. */
061:            protected int defaultColumn = 60;
062:
063:            /** Is the stylesheet currently running an FO stylesheet? */
064:            protected boolean foStylesheet = false;
065:
066:            /** The current line number. */
067:            private static int lineNumber = 0;
068:
069:            /** The current column number. */
070:            private static int colNumber = 0;
071:
072:            /** The (sorted) array of callouts obtained from the areaspec. */
073:            private static Callout callout[] = null;
074:
075:            /** The number of callouts in the callout array. */
076:            private static int calloutCount = 0;
077:
078:            /** A pointer used to keep track of our position in the callout array. */
079:            private static int calloutPos = 0;
080:
081:            /** The FormatCallout object to use for formatting callouts. */
082:            private static FormatCallout fCallout = null;
083:
084:            /** <p>Constructor for the CalloutEmitter.</p>
085:             *
086:             * @param namePool The name pool to use for constructing elements and attributes.
087:             * @param graphicsPath The path to callout number graphics.
088:             * @param graphicsExt The extension for callout number graphics.
089:             * @param graphicsMax The largest callout number that can be represented as a graphic.
090:             * @param defaultColumn The default column for callouts.
091:             * @param foStylesheet Is this an FO stylesheet?
092:             */
093:            public CalloutEmitter(Controller controller, NamePool namePool,
094:                    int defaultColumn, boolean foStylesheet,
095:                    FormatCallout fCallout) {
096:                super (controller, namePool);
097:                elementStack = new Stack();
098:                firstElement = true;
099:
100:                this .defaultColumn = defaultColumn;
101:                this .foStylesheet = foStylesheet;
102:                this .fCallout = fCallout;
103:            }
104:
105:            /**
106:             * <p>Examine the areaspec and determine the number and position of 
107:             * callouts.</p>
108:             *
109:             * <p>The <code><a href="http://docbook.org/tdg/html/areaspec.html">areaspecNodeSet</a></code>
110:             * is examined and a sorted list of the callouts is constructed.</p>
111:             *
112:             * <p>This data structure is used to augment the result tree fragment
113:             * with callout bullets.</p>
114:             *
115:             * @param areaspecNodeSet The source document &lt;areaspec&gt; element.
116:             *
117:             */
118:            public void setupCallouts(NodeList areaspecNodeList) {
119:                callout = new Callout[10];
120:                calloutCount = 0;
121:                calloutPos = 0;
122:                lineNumber = 1;
123:                colNumber = 1;
124:
125:                // First we walk through the areaspec to calculate the position
126:                // of the callouts
127:                //  <areaspec>
128:                //  <areaset id="ex.plco.const" coords="">
129:                //    <area id="ex.plco.c1" coords="4"/>
130:                //    <area id="ex.plco.c2" coords="8"/>
131:                //  </areaset>
132:                //  <area id="ex.plco.ret" coords="12"/>
133:                //  <area id="ex.plco.dest" coords="12"/>
134:                //  </areaspec>
135:                int pos = 0;
136:                int coNum = 0;
137:                boolean inAreaSet = false;
138:                Node areaspec = areaspecNodeList.item(0);
139:                NodeList children = areaspec.getChildNodes();
140:
141:                for (int count = 0; count < children.getLength(); count++) {
142:                    Node node = children.item(count);
143:                    if (node.getNodeType() == Node.ELEMENT_NODE) {
144:                        if (node.getNodeName().equalsIgnoreCase("areaset")) {
145:                            coNum++;
146:                            NodeList areas = node.getChildNodes();
147:                            for (int acount = 0; acount < areas.getLength(); acount++) {
148:                                Node area = areas.item(acount);
149:                                if (area.getNodeType() == Node.ELEMENT_NODE) {
150:                                    if (area.getNodeName().equalsIgnoreCase(
151:                                            "area")) {
152:                                        addCallout(coNum, area, defaultColumn);
153:                                    } else {
154:                                        System.out
155:                                                .println("Unexpected element in areaset: "
156:                                                        + area.getNodeName());
157:                                    }
158:                                }
159:                            }
160:                        } else if (node.getNodeName().equalsIgnoreCase("area")) {
161:                            coNum++;
162:                            addCallout(coNum, node, defaultColumn);
163:                        } else {
164:                            System.out
165:                                    .println("Unexpected element in areaspec: "
166:                                            + node.getNodeName());
167:                        }
168:                    }
169:                }
170:
171:                // Now sort them
172:                java.util.Arrays.sort(callout, 0, calloutCount);
173:            }
174:
175:            /** Process characters. */
176:            public void characters(char[] chars, int start, int len)
177:                    throws TransformerException {
178:
179:                // If we hit characters, then there's no first element...
180:                firstElement = false;
181:
182:                if (lineNumber == 0) {
183:                    // if there are any text nodes, there's at least one line
184:                    lineNumber++;
185:                    colNumber = 1;
186:                }
187:
188:                // Walk through the text node looking for callout positions
189:                char[] newChars = new char[len];
190:                int pos = 0;
191:                for (int count = start; count < start + len; count++) {
192:                    if (calloutPos < calloutCount
193:                            && callout[calloutPos].getLine() == lineNumber
194:                            && callout[calloutPos].getColumn() == colNumber) {
195:                        if (pos > 0) {
196:                            rtfEmitter.characters(newChars, 0, pos);
197:                            pos = 0;
198:                        }
199:
200:                        closeOpenElements(rtfEmitter);
201:
202:                        while (calloutPos < calloutCount
203:                                && callout[calloutPos].getLine() == lineNumber
204:                                && callout[calloutPos].getColumn() == colNumber) {
205:                            fCallout.formatCallout(rtfEmitter,
206:                                    callout[calloutPos]);
207:                            calloutPos++;
208:                        }
209:
210:                        openClosedElements(rtfEmitter);
211:                    }
212:
213:                    if (chars[count] == '\n') {
214:                        // What if we need to pad this line?
215:                        if (calloutPos < calloutCount
216:                                && callout[calloutPos].getLine() == lineNumber
217:                                && callout[calloutPos].getColumn() > colNumber) {
218:
219:                            if (pos > 0) {
220:                                rtfEmitter.characters(newChars, 0, pos);
221:                                pos = 0;
222:                            }
223:
224:                            closeOpenElements(rtfEmitter);
225:
226:                            while (calloutPos < calloutCount
227:                                    && callout[calloutPos].getLine() == lineNumber
228:                                    && callout[calloutPos].getColumn() > colNumber) {
229:                                formatPad(callout[calloutPos].getColumn()
230:                                        - colNumber);
231:                                colNumber = callout[calloutPos].getColumn();
232:                                while (calloutPos < calloutCount
233:                                        && callout[calloutPos].getLine() == lineNumber
234:                                        && callout[calloutPos].getColumn() == colNumber) {
235:                                    fCallout.formatCallout(rtfEmitter,
236:                                            callout[calloutPos]);
237:                                    calloutPos++;
238:                                }
239:                            }
240:
241:                            openClosedElements(rtfEmitter);
242:                        }
243:
244:                        lineNumber++;
245:                        colNumber = 1;
246:                    } else {
247:                        colNumber++;
248:                    }
249:                    newChars[pos++] = chars[count];
250:                }
251:
252:                if (pos > 0) {
253:                    rtfEmitter.characters(newChars, 0, pos);
254:                }
255:            }
256:
257:            /**
258:             * <p>Add blanks to the result tree fragment.</p>
259:             *
260:             * <p>This method adds <tt>numBlanks</tt> to the result tree fragment.
261:             * It's used to pad lines when callouts occur after the last existing
262:             * characater in a line.</p>
263:             *
264:             * @param numBlanks The number of blanks to add.
265:             */
266:            protected void formatPad(int numBlanks) {
267:                char chars[] = new char[numBlanks];
268:                for (int count = 0; count < numBlanks; count++) {
269:                    chars[count] = ' ';
270:                }
271:
272:                try {
273:                    rtfEmitter.characters(chars, 0, numBlanks);
274:                } catch (TransformerException e) {
275:                    System.out.println("Transformer Exception in formatPad");
276:                }
277:            }
278:
279:            /**
280:             * <p>Add a callout to the global callout array</p>
281:             *
282:             * <p>This method examines a callout <tt>area</tt> and adds it to
283:             * the global callout array if it can be interpreted.</p>
284:             *
285:             * <p>Only the <tt>linecolumn</tt> and <tt>linerange</tt> units are
286:             * supported. If no unit is specifed, <tt>linecolumn</tt> is assumed.
287:             * If only a line is specified, the callout decoration appears in
288:             * the <tt>defaultColumn</tt>.</p>
289:             *
290:             * @param coNum The callout number.
291:             * @param node The <tt>area</tt>.
292:             * @param defaultColumn The default column for callouts.
293:             */
294:            protected void addCallout(int coNum, Node node, int defaultColumn) {
295:
296:                Element area = (Element) node;
297:                String units = null;
298:                String coords = null;
299:
300:                if (area.hasAttribute("units")) {
301:                    units = area.getAttribute("units");
302:                }
303:
304:                if (area.hasAttribute("coords")) {
305:                    coords = area.getAttribute("coords");
306:                }
307:
308:                if (units != null && !units.equalsIgnoreCase("linecolumn")
309:                        && !units.equalsIgnoreCase("linerange")) {
310:                    System.out
311:                            .println("Only linecolumn and linerange units are supported");
312:                    return;
313:                }
314:
315:                if (coords == null) {
316:                    System.out.println("Coords must be specified");
317:                    return;
318:                }
319:
320:                // Now let's see if we can interpret the coordinates...
321:                StringTokenizer st = new StringTokenizer(coords);
322:                int tokenCount = 0;
323:                int c1 = 0;
324:                int c2 = 0;
325:                while (st.hasMoreTokens()) {
326:                    tokenCount++;
327:                    if (tokenCount > 2) {
328:                        System.out.println("Unparseable coordinates");
329:                        return;
330:                    }
331:                    try {
332:                        String token = st.nextToken();
333:                        int coord = Integer.parseInt(token);
334:                        c2 = coord;
335:                        if (tokenCount == 1) {
336:                            c1 = coord;
337:                        }
338:                    } catch (NumberFormatException e) {
339:                        System.out.println("Unparseable coordinate");
340:                        return;
341:                    }
342:                }
343:
344:                // Make sure we aren't going to blow past the end of our array
345:                if (calloutCount == callout.length) {
346:                    Callout bigger[] = new Callout[calloutCount + 10];
347:                    for (int count = 0; count < callout.length; count++) {
348:                        bigger[count] = callout[count];
349:                    }
350:                    callout = bigger;
351:                }
352:
353:                // Ok, add the callout
354:                if (tokenCount == 2) {
355:                    if (units != null && units.equalsIgnoreCase("linerange")) {
356:                        for (int count = c1; count <= c2; count++) {
357:                            callout[calloutCount++] = new Callout(coNum, area,
358:                                    count, defaultColumn);
359:                        }
360:                    } else {
361:                        // assume linecolumn
362:                        callout[calloutCount++] = new Callout(coNum, area, c1,
363:                                c2);
364:                    }
365:                } else {
366:                    // if there's only one number, assume it's the line
367:                    callout[calloutCount++] = new Callout(coNum, area, c1,
368:                            defaultColumn);
369:                }
370:            }
371:
372:            /** Process end element events. */
373:            public void endElement(int nameCode) throws TransformerException {
374:
375:                if (!elementStack.empty()) {
376:                    // if we didn't push the very first element (an fo:block or
377:                    // pre or div surrounding the whole block), then the stack will
378:                    // be empty when we get to the end of the first element...
379:                    elementStack.pop();
380:                }
381:                rtfEmitter.endElement(nameCode);
382:            }
383:
384:            /** Process start element events. */
385:            public void startElement(int nameCode,
386:                    org.xml.sax.Attributes attributes, int[] namespaces,
387:                    int nscount) throws TransformerException {
388:
389:                if (!skipThisElement(nameCode)) {
390:                    StartElementInfo sei = new StartElementInfo(nameCode,
391:                            attributes, namespaces, nscount);
392:                    elementStack.push(sei);
393:                }
394:
395:                firstElement = false;
396:
397:                rtfEmitter.startElement(nameCode, attributes, namespaces,
398:                        nscount);
399:            }
400:
401:            /**
402:             * <p>Protect the outer-most block wrapper.</p>
403:             *
404:             * <p>Open elements in the result tree fragment are closed and reopened
405:             * around callouts (so that callouts don't appear inside links or other
406:             * environments). But if the result tree fragment is a single block
407:             * (a div or pre in HTML, an fo:block in FO), that outer-most block is
408:             * treated specially.</p>
409:             *
410:             * <p>This method returns true if the element in question is that
411:             * outermost block.</p>
412:             *
413:             * @param nameCode The name code for the element
414:             *
415:             * @return True if the element is the outer-most block, false otherwise.
416:             */
417:            protected boolean skipThisElement(int nameCode) {
418:                if (firstElement) {
419:                    int this Fingerprint = namePool.getFingerprint(nameCode);
420:                    int foBlockFingerprint = namePool.getFingerprint(foURI,
421:                            "block");
422:                    int htmlPreFingerprint = namePool.getFingerprint("", "pre");
423:                    int htmlDivFingerprint = namePool.getFingerprint("", "div");
424:
425:                    if ((foStylesheet && this Fingerprint == foBlockFingerprint)
426:                            || (!foStylesheet && (this Fingerprint == htmlPreFingerprint || this Fingerprint == htmlDivFingerprint))) {
427:                        // Don't push the outer-most wrapping div, pre, or fo:block
428:                        return true;
429:                    }
430:                }
431:
432:                return false;
433:            }
434:
435:            private void closeOpenElements(Emitter rtfEmitter)
436:                    throws TransformerException {
437:                // Close all the open elements...
438:                tempStack = new Stack();
439:                while (!elementStack.empty()) {
440:                    StartElementInfo elem = (StartElementInfo) elementStack
441:                            .pop();
442:                    rtfEmitter.endElement(elem.getNameCode());
443:                    tempStack.push(elem);
444:                }
445:            }
446:
447:            private void openClosedElements(Emitter rtfEmitter)
448:                    throws TransformerException {
449:                // Now "reopen" the elements that we closed...
450:                while (!tempStack.empty()) {
451:                    StartElementInfo elem = (StartElementInfo) tempStack.pop();
452:                    AttributeCollection attr = (AttributeCollection) elem
453:                            .getAttributes();
454:                    AttributeCollection newAttr = new AttributeCollection(
455:                            namePool);
456:
457:                    for (int acount = 0; acount < attr.getLength(); acount++) {
458:                        String localName = attr.getLocalName(acount);
459:                        int nameCode = attr.getNameCode(acount);
460:                        String type = attr.getType(acount);
461:                        String value = attr.getValue(acount);
462:                        String uri = attr.getURI(acount);
463:                        String prefix = "";
464:
465:                        if (localName.indexOf(':') > 0) {
466:                            prefix = localName.substring(0, localName
467:                                    .indexOf(':'));
468:                            localName = localName.substring(localName
469:                                    .indexOf(':') + 1);
470:                        }
471:
472:                        if (uri.equals("")
473:                                && ((foStylesheet && localName.equals("id")) || (!foStylesheet && (localName
474:                                        .equals("id") || localName
475:                                        .equals("name"))))) {
476:                            // skip this attribute
477:                        } else {
478:                            newAttr.addAttribute(prefix, uri, localName, type,
479:                                    value);
480:                        }
481:                    }
482:
483:                    rtfEmitter.startElement(elem.getNameCode(), newAttr, elem
484:                            .getNamespaces(), elem.getNSCount());
485:
486:                    elementStack.push(elem);
487:                }
488:            }
489:
490:            /**
491:             * <p>A private class for maintaining the information required to call
492:             * the startElement method.</p>
493:             *
494:             * <p>In order to close and reopen elements, information about those
495:             * elements has to be maintained. This class is just the little record
496:             * that we push on the stack to keep track of that info.</p>
497:             */
498:            private class StartElementInfo {
499:                private int _nameCode;
500:                org.xml.sax.Attributes _attributes;
501:                int[] _namespaces;
502:                int _nscount;
503:
504:                public StartElementInfo(int nameCode,
505:                        org.xml.sax.Attributes attributes, int[] namespaces,
506:                        int nscount) {
507:                    _nameCode = nameCode;
508:                    _attributes = attributes;
509:                    _namespaces = namespaces;
510:                    _nscount = nscount;
511:                }
512:
513:                public int getNameCode() {
514:                    return _nameCode;
515:                }
516:
517:                public org.xml.sax.Attributes getAttributes() {
518:                    return _attributes;
519:                }
520:
521:                public int[] getNamespaces() {
522:                    return _namespaces;
523:                }
524:
525:                public int getNSCount() {
526:                    return _nscount;
527:                }
528:            }
529:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.