Source Code Cross Referenced for XfaForm.java in  » PDF » pdf-itext » com » lowagie » text » pdf » 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 » PDF » pdf itext » com.lowagie.text.pdf 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $Id: XfaForm.java 2768 2007-05-21 08:48:44Z blowagie $
0003:         *
0004:         * Copyright 2006 Paulo Soares
0005:         *
0006:         * The contents of this file are subject to the Mozilla Public License Version 1.1
0007:         * (the "License"); you may not use this file except in compliance with the License.
0008:         * You may obtain a copy of the License at http://www.mozilla.org/MPL/
0009:         *
0010:         * Software distributed under the License is distributed on an "AS IS" basis,
0011:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
0012:         * for the specific language governing rights and limitations under the License.
0013:         *
0014:         * The Original Code is 'iText, a free JAVA-PDF library'.
0015:         *
0016:         * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
0017:         * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
0018:         * All Rights Reserved.
0019:         * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
0020:         * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
0021:         *
0022:         * Contributor(s): all the names of the contributors are added in the source code
0023:         * where applicable.
0024:         *
0025:         * Alternatively, the contents of this file may be used under the terms of the
0026:         * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
0027:         * provisions of LGPL are applicable instead of those above.  If you wish to
0028:         * allow use of your version of this file only under the terms of the LGPL
0029:         * License and not to allow others to use your version of this file under
0030:         * the MPL, indicate your decision by deleting the provisions above and
0031:         * replace them with the notice and other provisions required by the LGPL.
0032:         * If you do not delete the provisions above, a recipient may use your version
0033:         * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
0034:         *
0035:         * This library is free software; you can redistribute it and/or modify it
0036:         * under the terms of the MPL as stated above or under the terms of the GNU
0037:         * Library General Public License as published by the Free Software Foundation;
0038:         * either version 2 of the License, or any later version.
0039:         *
0040:         * This library is distributed in the hope that it will be useful, but WITHOUT
0041:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
0042:         * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
0043:         * details.
0044:         *
0045:         * If you didn't download this code from the following link, you should check if
0046:         * you aren't using an obsolete version:
0047:         * http://www.lowagie.com/iText/
0048:         */
0049:
0050:        package com.lowagie.text.pdf;
0051:
0052:        import java.io.ByteArrayInputStream;
0053:        import java.io.ByteArrayOutputStream;
0054:        import java.io.IOException;
0055:        import java.util.ArrayList;
0056:        import java.util.Collection;
0057:        import java.util.EmptyStackException;
0058:        import java.util.HashMap;
0059:        import java.util.Iterator;
0060:
0061:        import javax.xml.parsers.DocumentBuilder;
0062:        import javax.xml.parsers.DocumentBuilderFactory;
0063:        import javax.xml.parsers.ParserConfigurationException;
0064:
0065:        import org.w3c.dom.Node;
0066:        import org.xml.sax.SAXException;
0067:
0068:        import com.lowagie.text.xml.XmlDomWriter;
0069:
0070:        /**
0071:         * Processes XFA forms.
0072:         * @author Paulo Soares (psoares@consiste.pt)
0073:         */
0074:        public class XfaForm {
0075:
0076:            private Xml2SomTemplate templateSom;
0077:            private Xml2SomDatasets datasetsSom;
0078:            private AcroFieldsSearch acroFieldsSom;
0079:            private PdfReader reader;
0080:            private boolean xfaPresent;
0081:            private org.w3c.dom.Document domDocument;
0082:            private boolean changed;
0083:            private Node datasetsNode;
0084:            public static final String XFA_DATA_SCHEMA = "http://www.xfa.org/schema/xfa-data/1.0/";
0085:
0086:            /**
0087:             * An empty constructor to build on.
0088:             */
0089:            public XfaForm() {
0090:            }
0091:
0092:            /**
0093:             * A constructor from a <CODE>PdfReader</CODE>. It basically does everything
0094:             * from finding the XFA stream to the XML parsing.
0095:             * @param reader the reader
0096:             * @throws java.io.IOException on error
0097:             * @throws javax.xml.parsers.ParserConfigurationException on error
0098:             * @throws org.xml.sax.SAXException on error
0099:             */
0100:            public XfaForm(PdfReader reader) throws IOException,
0101:                    ParserConfigurationException, SAXException {
0102:                this .reader = reader;
0103:                PdfDictionary af = (PdfDictionary) PdfReader
0104:                        .getPdfObjectRelease(reader.getCatalog().get(
0105:                                PdfName.ACROFORM));
0106:                if (af == null) {
0107:                    xfaPresent = false;
0108:                    return;
0109:                }
0110:                PdfObject xfa = PdfReader.getPdfObjectRelease(af
0111:                        .get(PdfName.XFA));
0112:                if (xfa == null) {
0113:                    xfaPresent = false;
0114:                    return;
0115:                }
0116:                xfaPresent = true;
0117:                ByteArrayOutputStream bout = new ByteArrayOutputStream();
0118:                if (xfa.isArray()) {
0119:                    ArrayList ar = ((PdfArray) xfa).getArrayList();
0120:                    for (int k = 1; k < ar.size(); k += 2) {
0121:                        PdfObject ob = PdfReader.getPdfObject((PdfObject) ar
0122:                                .get(k));
0123:                        if (ob instanceof  PRStream) {
0124:                            byte[] b = PdfReader.getStreamBytes((PRStream) ob);
0125:                            bout.write(b);
0126:                        }
0127:                    }
0128:                } else if (xfa instanceof  PRStream) {
0129:                    byte[] b = PdfReader.getStreamBytes((PRStream) xfa);
0130:                    bout.write(b);
0131:                }
0132:                bout.close();
0133:                DocumentBuilderFactory fact = DocumentBuilderFactory
0134:                        .newInstance();
0135:                fact.setNamespaceAware(true);
0136:                DocumentBuilder db = fact.newDocumentBuilder();
0137:                domDocument = db.parse(new ByteArrayInputStream(bout
0138:                        .toByteArray()));
0139:                Node n = domDocument.getFirstChild();
0140:                n = n.getFirstChild();
0141:                while (n != null) {
0142:                    if (n.getNodeType() == Node.ELEMENT_NODE) {
0143:                        String s = n.getLocalName();
0144:                        if (s.equals("template")) {
0145:                            templateSom = new Xml2SomTemplate(n);
0146:                        } else if (s.equals("datasets")) {
0147:                            datasetsNode = n;
0148:                            datasetsSom = new Xml2SomDatasets(n.getFirstChild());
0149:                        }
0150:                    }
0151:                    n = n.getNextSibling();
0152:                }
0153:            }
0154:
0155:            /**
0156:             * Sets the XFA key from a byte array. The old XFA is erased.
0157:             * @param xfaData the data
0158:             * @param reader the reader
0159:             * @param writer the writer
0160:             * @throws java.io.IOException on error
0161:             */
0162:            public static void setXfa(byte[] xfaData, PdfReader reader,
0163:                    PdfWriter writer) throws IOException {
0164:                PdfDictionary af = (PdfDictionary) PdfReader
0165:                        .getPdfObjectRelease(reader.getCatalog().get(
0166:                                PdfName.ACROFORM));
0167:                if (af == null) {
0168:                    return;
0169:                }
0170:                reader.killXref(af.get(PdfName.XFA));
0171:                PdfStream str = new PdfStream(xfaData);
0172:                str.flateCompress();
0173:                PdfIndirectReference ref = writer.addToBody(str)
0174:                        .getIndirectReference();
0175:                af.put(PdfName.XFA, ref);
0176:            }
0177:
0178:            /**
0179:             * Sets the XFA key from the instance data. The old XFA is erased.
0180:             * @param writer the writer
0181:             * @throws java.io.IOException on error
0182:             */
0183:            public void setXfa(PdfWriter writer) throws IOException {
0184:                setXfa(serializeDoc(domDocument), reader, writer);
0185:            }
0186:
0187:            /**
0188:             * Serializes a XML document to a byte array.
0189:             * @param n the XML document
0190:             * @throws java.io.IOException on error
0191:             * @return the serialized XML document
0192:             */
0193:            public static byte[] serializeDoc(Node n) throws IOException {
0194:                XmlDomWriter xw = new XmlDomWriter();
0195:                ByteArrayOutputStream fout = new ByteArrayOutputStream();
0196:                xw.setOutput(fout, null);
0197:                xw.setCanonical(false);
0198:                xw.write(n);
0199:                fout.close();
0200:                return fout.toByteArray();
0201:            }
0202:
0203:            /**
0204:             * Returns <CODE>true</CODE> if it is a XFA form.
0205:             * @return <CODE>true</CODE> if it is a XFA form
0206:             */
0207:            public boolean isXfaPresent() {
0208:                return xfaPresent;
0209:            }
0210:
0211:            /**
0212:             * Gets the top level DOM document.
0213:             * @return the top level DOM document
0214:             */
0215:            public org.w3c.dom.Document getDomDocument() {
0216:                return domDocument;
0217:            }
0218:
0219:            /**
0220:             * Finds the complete field name contained in the "classic" forms from a partial
0221:             * name.
0222:             * @param name the complete or partial name
0223:             * @param af the fields
0224:             * @return the complete name or <CODE>null</CODE> if not found
0225:             */
0226:            public String findFieldName(String name, AcroFields af) {
0227:                HashMap items = af.getFields();
0228:                if (items.containsKey(name))
0229:                    return name;
0230:                if (acroFieldsSom == null) {
0231:                    acroFieldsSom = new AcroFieldsSearch(items.keySet());
0232:                }
0233:                if (acroFieldsSom.getAcroShort2LongName().containsKey(name))
0234:                    return (String) acroFieldsSom.getAcroShort2LongName().get(
0235:                            name);
0236:                return acroFieldsSom.inverseSearchGlobal(Xml2Som
0237:                        .splitParts(name));
0238:            }
0239:
0240:            /**
0241:             * Finds the complete SOM name contained in the datasets section from a 
0242:             * possibly partial name.
0243:             * @param name the complete or partial name
0244:             * @return the complete name or <CODE>null</CODE> if not found
0245:             */
0246:            public String findDatasetsName(String name) {
0247:                if (datasetsSom.getName2Node().containsKey(name))
0248:                    return name;
0249:                return datasetsSom
0250:                        .inverseSearchGlobal(Xml2Som.splitParts(name));
0251:            }
0252:
0253:            /**
0254:             * Finds the <CODE>Node</CODE> contained in the datasets section from a 
0255:             * possibly partial name.
0256:             * @param name the complete or partial name
0257:             * @return the <CODE>Node</CODE> or <CODE>null</CODE> if not found
0258:             */
0259:            public Node findDatasetsNode(String name) {
0260:                if (name == null)
0261:                    return null;
0262:                name = findDatasetsName(name);
0263:                if (name == null)
0264:                    return null;
0265:                return (Node) datasetsSom.getName2Node().get(name);
0266:            }
0267:
0268:            /**
0269:             * Gets all the text contained in the child nodes of this node.
0270:             * @param n the <CODE>Node</CODE>
0271:             * @return the text found or "" if no text was found
0272:             */
0273:            public static String getNodeText(Node n) {
0274:                if (n == null)
0275:                    return "";
0276:                return getNodeText(n, "");
0277:
0278:            }
0279:
0280:            private static String getNodeText(Node n, String name) {
0281:                Node n2 = n.getFirstChild();
0282:                while (n2 != null) {
0283:                    if (n2.getNodeType() == Node.ELEMENT_NODE) {
0284:                        name = getNodeText(n2, name);
0285:                    } else if (n2.getNodeType() == Node.TEXT_NODE) {
0286:                        name += n2.getNodeValue();
0287:                    }
0288:                    n2 = n2.getNextSibling();
0289:                }
0290:                return name;
0291:            }
0292:
0293:            /**
0294:             * Sets the text of this node. All the child's node are deleted and a new
0295:             * child text node is created.
0296:             * @param n the <CODE>Node</CODE> to add the text to
0297:             * @param text the text to add
0298:             */
0299:            public void setNodeText(Node n, String text) {
0300:                if (n == null)
0301:                    return;
0302:                Node nc = null;
0303:                while ((nc = n.getFirstChild()) != null) {
0304:                    n.removeChild(nc);
0305:                }
0306:                if (n.getAttributes().getNamedItemNS(XFA_DATA_SCHEMA,
0307:                        "dataNode") != null)
0308:                    n.getAttributes().removeNamedItemNS(XFA_DATA_SCHEMA,
0309:                            "dataNode");
0310:                n.appendChild(domDocument.createTextNode(text));
0311:                changed = true;
0312:            }
0313:
0314:            /**
0315:             * Sets the XFA form flag signaling that this is a valid XFA form.
0316:             * @param xfaPresent the XFA form flag signaling that this is a valid XFA form
0317:             */
0318:            public void setXfaPresent(boolean xfaPresent) {
0319:                this .xfaPresent = xfaPresent;
0320:            }
0321:
0322:            /**
0323:             * Sets the top DOM document.
0324:             * @param domDocument the top DOM document
0325:             */
0326:            public void setDomDocument(org.w3c.dom.Document domDocument) {
0327:                this .domDocument = domDocument;
0328:            }
0329:
0330:            /**
0331:             * Gets the <CODE>PdfReader</CODE> used by this instance.
0332:             * @return the <CODE>PdfReader</CODE> used by this instance
0333:             */
0334:            public PdfReader getReader() {
0335:                return reader;
0336:            }
0337:
0338:            /**
0339:             * Sets the <CODE>PdfReader</CODE> to be used by this instance.
0340:             * @param reader the <CODE>PdfReader</CODE> to be used by this instance
0341:             */
0342:            public void setReader(PdfReader reader) {
0343:                this .reader = reader;
0344:            }
0345:
0346:            /**
0347:             * Checks if this XFA form was changed.
0348:             * @return <CODE>true</CODE> if this XFA form was changed
0349:             */
0350:            public boolean isChanged() {
0351:                return changed;
0352:            }
0353:
0354:            /**
0355:             * Sets the changed status of this XFA instance.
0356:             * @param changed the changed status of this XFA instance
0357:             */
0358:            public void setChanged(boolean changed) {
0359:                this .changed = changed;
0360:            }
0361:
0362:            /**
0363:             * A structure to store each part of a SOM name and link it to the next part
0364:             * beginning from the lower hierarchie.
0365:             */
0366:            public static class InverseStore {
0367:                protected ArrayList part = new ArrayList();
0368:                protected ArrayList follow = new ArrayList();
0369:
0370:                /**
0371:                 * Gets the full name by traversing the hiearchie using only the
0372:                 * index 0.
0373:                 * @return the full name
0374:                 */
0375:                public String getDefaultName() {
0376:                    InverseStore store = this ;
0377:                    while (true) {
0378:                        Object obj = store.follow.get(0);
0379:                        if (obj instanceof  String)
0380:                            return (String) obj;
0381:                        store = (InverseStore) obj;
0382:                    }
0383:                }
0384:
0385:                /**
0386:                 * Search the current node for a similar name. A similar name starts
0387:                 * with the same name but has a differnt index. For example, "detail[3]" 
0388:                 * is similar to "detail[9]". The main use is to discard names that
0389:                 * correspond to out of bounds records.
0390:                 * @param name the name to search
0391:                 * @return <CODE>true</CODE> if a similitude was found
0392:                 */
0393:                public boolean isSimilar(String name) {
0394:                    int idx = name.indexOf('[');
0395:                    name = name.substring(0, idx + 1);
0396:                    for (int k = 0; k < part.size(); ++k) {
0397:                        if (((String) part.get(k)).startsWith(name))
0398:                            return true;
0399:                    }
0400:                    return false;
0401:                }
0402:            }
0403:
0404:            /**
0405:             * Another stack implementation. The main use is to facilitate
0406:             * the porting to other languages.
0407:             */
0408:            public static class Stack2 extends ArrayList {
0409:                private static final long serialVersionUID = -7451476576174095212L;
0410:
0411:                /**
0412:                 * Looks at the object at the top of this stack without removing it from the stack.
0413:                 * @return the object at the top of this stack
0414:                 */
0415:                public Object peek() {
0416:                    if (size() == 0)
0417:                        throw new EmptyStackException();
0418:                    return get(size() - 1);
0419:                }
0420:
0421:                /**
0422:                 * Removes the object at the top of this stack and returns that object as the value of this function.
0423:                 * @return the object at the top of this stack 
0424:                 */
0425:                public Object pop() {
0426:                    if (size() == 0)
0427:                        throw new EmptyStackException();
0428:                    Object ret = get(size() - 1);
0429:                    remove(size() - 1);
0430:                    return ret;
0431:                }
0432:
0433:                /**
0434:                 * Pushes an item onto the top of this stack.
0435:                 * @param item the item to be pushed onto this stack
0436:                 * @return the <CODE>item</CODE> argument
0437:                 */
0438:                public Object push(Object item) {
0439:                    add(item);
0440:                    return item;
0441:                }
0442:
0443:                /**
0444:                 * Tests if this stack is empty.
0445:                 * @return <CODE>true</CODE> if and only if this stack contains no items; <CODE>false</CODE> otherwise
0446:                 */
0447:                public boolean empty() {
0448:                    return size() == 0;
0449:                }
0450:            }
0451:
0452:            /**
0453:             * A class for some basic SOM processing.
0454:             */
0455:            public static class Xml2Som {
0456:                /**
0457:                 * The order the names appear in the XML, depth first.
0458:                 */
0459:                protected ArrayList order;
0460:                /**
0461:                 * The mapping of full names to nodes.
0462:                 */
0463:                protected HashMap name2Node;
0464:                /**
0465:                 * The data to do a search from the bottom hierarchie.
0466:                 */
0467:                protected HashMap inverseSearch;
0468:                /**
0469:                 * A stack to be used when parsing.
0470:                 */
0471:                protected Stack2 stack;
0472:                /**
0473:                 * A temporary store for the repetition count.
0474:                 */
0475:                protected int anform;
0476:
0477:                /**
0478:                 * Escapes a SOM string fragment replacing "." with "\.".
0479:                 * @param s the unescaped string
0480:                 * @return the escaped string
0481:                 */
0482:                public static String escapeSom(String s) {
0483:                    int idx = s.indexOf('.');
0484:                    if (idx < 0)
0485:                        return s;
0486:                    StringBuffer sb = new StringBuffer();
0487:                    int last = 0;
0488:                    while (idx >= 0) {
0489:                        sb.append(s.substring(last, idx));
0490:                        sb.append('\\');
0491:                        last = idx;
0492:                        idx = s.indexOf('.', idx + 1);
0493:                    }
0494:                    sb.append(s.substring(last));
0495:                    return sb.toString();
0496:                }
0497:
0498:                /**
0499:                 * Unescapes a SOM string fragment replacing "\." with ".".
0500:                 * @param s the escaped string
0501:                 * @return the unescaped string
0502:                 */
0503:                public static String unescapeSom(String s) {
0504:                    int idx = s.indexOf('\\');
0505:                    if (idx < 0)
0506:                        return s;
0507:                    StringBuffer sb = new StringBuffer();
0508:                    int last = 0;
0509:                    while (idx >= 0) {
0510:                        sb.append(s.substring(last, idx));
0511:                        last = idx + 1;
0512:                        idx = s.indexOf('\\', idx + 1);
0513:                    }
0514:                    sb.append(s.substring(last));
0515:                    return sb.toString();
0516:                }
0517:
0518:                /**
0519:                 * Outputs the stack as the sequence of elements separated
0520:                 * by '.'.
0521:                 * @return the stack as the sequence of elements separated by '.'
0522:                 */
0523:                protected String printStack() {
0524:                    if (stack.empty())
0525:                        return "";
0526:                    StringBuffer s = new StringBuffer();
0527:                    for (int k = 0; k < stack.size(); ++k)
0528:                        s.append('.').append((String) stack.get(k));
0529:                    return s.substring(1);
0530:                }
0531:
0532:                /**
0533:                 * Gets the name with the <CODE>#subform</CODE> removed.
0534:                 * @param s the long name
0535:                 * @return the short name
0536:                 */
0537:                public static String getShortName(String s) {
0538:                    int idx = s.indexOf(".#subform[");
0539:                    if (idx < 0)
0540:                        return s;
0541:                    int last = 0;
0542:                    StringBuffer sb = new StringBuffer();
0543:                    while (idx >= 0) {
0544:                        sb.append(s.substring(last, idx));
0545:                        idx = s.indexOf("]", idx + 10);
0546:                        if (idx < 0)
0547:                            return sb.toString();
0548:                        last = idx + 1;
0549:                        idx = s.indexOf(".#subform[", last);
0550:                    }
0551:                    sb.append(s.substring(last));
0552:                    return sb.toString();
0553:                }
0554:
0555:                /**
0556:                 * Adds a SOM name to the search node chain.
0557:                 * @param unstack the SOM name
0558:                 */
0559:                public void inverseSearchAdd(String unstack) {
0560:                    inverseSearchAdd(inverseSearch, stack, unstack);
0561:                }
0562:
0563:                /**
0564:                 * Adds a SOM name to the search node chain.
0565:                 * @param inverseSearch the start point
0566:                 * @param stack the stack with the separeted SOM parts
0567:                 * @param unstack the full name
0568:                 */
0569:                public static void inverseSearchAdd(HashMap inverseSearch,
0570:                        Stack2 stack, String unstack) {
0571:                    String last = (String) stack.peek();
0572:                    InverseStore store = (InverseStore) inverseSearch.get(last);
0573:                    if (store == null) {
0574:                        store = new InverseStore();
0575:                        inverseSearch.put(last, store);
0576:                    }
0577:                    for (int k = stack.size() - 2; k >= 0; --k) {
0578:                        last = (String) stack.get(k);
0579:                        InverseStore store2;
0580:                        int idx = store.part.indexOf(last);
0581:                        if (idx < 0) {
0582:                            store.part.add(last);
0583:                            store2 = new InverseStore();
0584:                            store.follow.add(store2);
0585:                        } else
0586:                            store2 = (InverseStore) store.follow.get(idx);
0587:                        store = store2;
0588:                    }
0589:                    store.part.add("");
0590:                    store.follow.add(unstack);
0591:                }
0592:
0593:                /**
0594:                 * Searchs the SOM hiearchie from the bottom.
0595:                 * @param parts the SOM parts
0596:                 * @return the full name or <CODE>null</CODE> if not found
0597:                 */
0598:                public String inverseSearchGlobal(ArrayList parts) {
0599:                    if (parts.isEmpty())
0600:                        return null;
0601:                    InverseStore store = (InverseStore) inverseSearch.get(parts
0602:                            .get(parts.size() - 1));
0603:                    if (store == null)
0604:                        return null;
0605:                    for (int k = parts.size() - 2; k >= 0; --k) {
0606:                        String part = (String) parts.get(k);
0607:                        int idx = store.part.indexOf(part);
0608:                        if (idx < 0) {
0609:                            if (store.isSimilar(part))
0610:                                return null;
0611:                            return store.getDefaultName();
0612:                        }
0613:                        store = (InverseStore) store.follow.get(idx);
0614:                    }
0615:                    return store.getDefaultName();
0616:                }
0617:
0618:                /**
0619:                 * Splits a SOM name in the individual parts.
0620:                 * @param name the full SOM name
0621:                 * @return the split name
0622:                 */
0623:                public static Stack2 splitParts(String name) {
0624:                    while (name.startsWith("."))
0625:                        name = name.substring(1);
0626:                    Stack2 parts = new Stack2();
0627:                    int last = 0;
0628:                    int pos = 0;
0629:                    String part;
0630:                    while (true) {
0631:                        pos = last;
0632:                        while (true) {
0633:                            pos = name.indexOf('.', pos);
0634:                            if (pos < 0)
0635:                                break;
0636:                            if (name.charAt(pos - 1) == '\\')
0637:                                ++pos;
0638:                            else
0639:                                break;
0640:                        }
0641:                        if (pos < 0)
0642:                            break;
0643:                        part = name.substring(last, pos);
0644:                        if (!part.endsWith("]"))
0645:                            part += "[0]";
0646:                        parts.add(part);
0647:                        last = pos + 1;
0648:                    }
0649:                    part = name.substring(last);
0650:                    if (!part.endsWith("]"))
0651:                        part += "[0]";
0652:                    parts.add(part);
0653:                    return parts;
0654:                }
0655:
0656:                /**
0657:                 * Gets the order the names appear in the XML, depth first.
0658:                 * @return the order the names appear in the XML, depth first
0659:                 */
0660:                public ArrayList getOrder() {
0661:                    return order;
0662:                }
0663:
0664:                /**
0665:                 * Sets the order the names appear in the XML, depth first
0666:                 * @param order the order the names appear in the XML, depth first
0667:                 */
0668:                public void setOrder(ArrayList order) {
0669:                    this .order = order;
0670:                }
0671:
0672:                /**
0673:                 * Gets the mapping of full names to nodes.
0674:                 * @return the mapping of full names to nodes
0675:                 */
0676:                public HashMap getName2Node() {
0677:                    return name2Node;
0678:                }
0679:
0680:                /**
0681:                 * Sets the mapping of full names to nodes.
0682:                 * @param name2Node the mapping of full names to nodes
0683:                 */
0684:                public void setName2Node(HashMap name2Node) {
0685:                    this .name2Node = name2Node;
0686:                }
0687:
0688:                /**
0689:                 * Gets the data to do a search from the bottom hierarchie.
0690:                 * @return the data to do a search from the bottom hierarchie
0691:                 */
0692:                public HashMap getInverseSearch() {
0693:                    return inverseSearch;
0694:                }
0695:
0696:                /**
0697:                 * Sets the data to do a search from the bottom hierarchie.
0698:                 * @param inverseSearch the data to do a search from the bottom hierarchie
0699:                 */
0700:                public void setInverseSearch(HashMap inverseSearch) {
0701:                    this .inverseSearch = inverseSearch;
0702:                }
0703:            }
0704:
0705:            /**
0706:             * Processes the datasets section in the XFA form.
0707:             */
0708:            public static class Xml2SomDatasets extends Xml2Som {
0709:                /**
0710:                 * Creates a new instance from the datasets node. This expects
0711:                 * not the datasets but the data node that comes below.
0712:                 * @param n the datasets node
0713:                 */
0714:                public Xml2SomDatasets(Node n) {
0715:                    order = new ArrayList();
0716:                    name2Node = new HashMap();
0717:                    stack = new Stack2();
0718:                    anform = 0;
0719:                    inverseSearch = new HashMap();
0720:                    processDatasetsInternal(n);
0721:                }
0722:
0723:                /**
0724:                 * Inserts a new <CODE>Node</CODE> that will match the short name.
0725:                 * @param n the datasets top <CODE>Node</CODE>
0726:                 * @param shortName the short name
0727:                 * @return the new <CODE>Node</CODE> of the inserted name
0728:                 */
0729:                public Node insertNode(Node n, String shortName) {
0730:                    Stack2 stack = splitParts(shortName);
0731:                    org.w3c.dom.Document doc = n.getOwnerDocument();
0732:                    Node n2 = null;
0733:                    n = n.getFirstChild();
0734:                    for (int k = 0; k < stack.size(); ++k) {
0735:                        String part = (String) stack.get(k);
0736:                        int idx = part.lastIndexOf('[');
0737:                        String name = part.substring(0, idx);
0738:                        idx = Integer.parseInt(part.substring(idx + 1, part
0739:                                .length() - 1));
0740:                        int found = -1;
0741:                        for (n2 = n.getFirstChild(); n2 != null; n2 = n2
0742:                                .getNextSibling()) {
0743:                            if (n2.getNodeType() == Node.ELEMENT_NODE) {
0744:                                String s = escapeSom(n2.getLocalName());
0745:                                if (s.equals(name)) {
0746:                                    ++found;
0747:                                    if (found == idx)
0748:                                        break;
0749:                                }
0750:                            }
0751:                        }
0752:                        for (; found < idx; ++found) {
0753:                            n2 = doc.createElementNS(null, name);
0754:                            n2 = n.appendChild(n2);
0755:                            Node attr = doc.createAttributeNS(XFA_DATA_SCHEMA,
0756:                                    "dataNode");
0757:                            attr.setNodeValue("dataGroup");
0758:                            n2.getAttributes().setNamedItemNS(attr);
0759:                        }
0760:                        n = n2;
0761:                    }
0762:                    inverseSearchAdd(inverseSearch, stack, shortName);
0763:                    name2Node.put(shortName, n2);
0764:                    order.add(shortName);
0765:                    return n2;
0766:                }
0767:
0768:                private static boolean hasChildren(Node n) {
0769:                    Node dataNodeN = n.getAttributes().getNamedItemNS(
0770:                            XFA_DATA_SCHEMA, "dataNode");
0771:                    if (dataNodeN != null) {
0772:                        String dataNode = dataNodeN.getNodeValue();
0773:                        if ("dataGroup".equals(dataNode))
0774:                            return true;
0775:                        else if ("dataValue".equals(dataNode))
0776:                            return false;
0777:                    }
0778:                    if (!n.hasChildNodes())
0779:                        return false;
0780:                    Node n2 = n.getFirstChild();
0781:                    while (n2 != null) {
0782:                        if (n2.getNodeType() == Node.ELEMENT_NODE) {
0783:                            return true;
0784:                        }
0785:                        n2 = n2.getNextSibling();
0786:                    }
0787:                    return false;
0788:                }
0789:
0790:                private void processDatasetsInternal(Node n) {
0791:                    HashMap ss = new HashMap();
0792:                    Node n2 = n.getFirstChild();
0793:                    while (n2 != null) {
0794:                        if (n2.getNodeType() == Node.ELEMENT_NODE) {
0795:                            String s = escapeSom(n2.getLocalName());
0796:                            Integer i = (Integer) ss.get(s);
0797:                            if (i == null)
0798:                                i = new Integer(0);
0799:                            else
0800:                                i = new Integer(i.intValue() + 1);
0801:                            ss.put(s, i);
0802:                            if (hasChildren(n2)) {
0803:                                stack.push(s + "[" + i.toString() + "]");
0804:                                processDatasetsInternal(n2);
0805:                                stack.pop();
0806:                            } else {
0807:                                stack.push(s + "[" + i.toString() + "]");
0808:                                String unstack = printStack();
0809:                                order.add(unstack);
0810:                                inverseSearchAdd(unstack);
0811:                                name2Node.put(unstack, n2);
0812:                                stack.pop();
0813:                            }
0814:                        }
0815:                        n2 = n2.getNextSibling();
0816:                    }
0817:                }
0818:            }
0819:
0820:            /**
0821:             * A class to process "classic" fields.
0822:             */
0823:            public static class AcroFieldsSearch extends Xml2Som {
0824:                private HashMap acroShort2LongName;
0825:
0826:                /**
0827:                 * Creates a new instance from a Collection with the full names.
0828:                 * @param items the Collection
0829:                 */
0830:                public AcroFieldsSearch(Collection items) {
0831:                    inverseSearch = new HashMap();
0832:                    acroShort2LongName = new HashMap();
0833:                    for (Iterator it = items.iterator(); it.hasNext();) {
0834:                        String itemName = (String) it.next();
0835:                        String itemShort = getShortName(itemName);
0836:                        acroShort2LongName.put(itemShort, itemName);
0837:                        inverseSearchAdd(inverseSearch, splitParts(itemShort),
0838:                                itemName);
0839:                    }
0840:                }
0841:
0842:                /**
0843:                 * Gets the mapping from short names to long names. A long 
0844:                 * name may contain the #subform name part.
0845:                 * @return the mapping from short names to long names
0846:                 */
0847:                public HashMap getAcroShort2LongName() {
0848:                    return acroShort2LongName;
0849:                }
0850:
0851:                /**
0852:                 * Sets the mapping from short names to long names. A long 
0853:                 * name may contain the #subform name part.
0854:                 * @param acroShort2LongName the mapping from short names to long names
0855:                 */
0856:                public void setAcroShort2LongName(HashMap acroShort2LongName) {
0857:                    this .acroShort2LongName = acroShort2LongName;
0858:                }
0859:            }
0860:
0861:            /**
0862:             * Processes the template section in the XFA form.
0863:             */
0864:            public static class Xml2SomTemplate extends Xml2Som {
0865:                private boolean dynamicForm;
0866:                private int templateLevel;
0867:
0868:                /**
0869:                 * Creates a new instance from the datasets node.
0870:                 * @param n the template node
0871:                 */
0872:                public Xml2SomTemplate(Node n) {
0873:                    order = new ArrayList();
0874:                    name2Node = new HashMap();
0875:                    stack = new Stack2();
0876:                    anform = 0;
0877:                    templateLevel = 0;
0878:                    inverseSearch = new HashMap();
0879:                    processTemplate(n, null);
0880:                }
0881:
0882:                /**
0883:                 * Gets the field type as described in the <CODE>template</CODE> section of the XFA.
0884:                 * @param s the exact template name
0885:                 * @return the field type or <CODE>null</CODE> if not found
0886:                 */
0887:                public String getFieldType(String s) {
0888:                    Node n = (Node) name2Node.get(s);
0889:                    if (n == null)
0890:                        return null;
0891:                    if (n.getLocalName().equals("exclGroup"))
0892:                        return "exclGroup";
0893:                    Node ui = n.getFirstChild();
0894:                    while (ui != null) {
0895:                        if (ui.getNodeType() == Node.ELEMENT_NODE
0896:                                && ui.getLocalName().equals("ui")) {
0897:                            break;
0898:                        }
0899:                        ui = ui.getNextSibling();
0900:                    }
0901:                    if (ui == null)
0902:                        return null;
0903:                    Node type = ui.getFirstChild();
0904:                    while (type != null) {
0905:                        if (type.getNodeType() == Node.ELEMENT_NODE
0906:                                && !(type.getLocalName().equals("extras") && type
0907:                                        .getLocalName().equals("picture"))) {
0908:                            return type.getLocalName();
0909:                        }
0910:                        type = type.getNextSibling();
0911:                    }
0912:                    return null;
0913:                }
0914:
0915:                private void processTemplate(Node n, HashMap ff) {
0916:                    if (ff == null)
0917:                        ff = new HashMap();
0918:                    HashMap ss = new HashMap();
0919:                    Node n2 = n.getFirstChild();
0920:                    while (n2 != null) {
0921:                        if (n2.getNodeType() == Node.ELEMENT_NODE) {
0922:                            String s = n2.getLocalName();
0923:                            if (s.equals("subform")) {
0924:                                Node name = n2.getAttributes().getNamedItem(
0925:                                        "name");
0926:                                String nn = "#subform";
0927:                                boolean annon = true;
0928:                                if (name != null) {
0929:                                    nn = escapeSom(name.getNodeValue());
0930:                                    annon = false;
0931:                                }
0932:                                Integer i;
0933:                                if (annon) {
0934:                                    i = new Integer(anform);
0935:                                    ++anform;
0936:                                } else {
0937:                                    i = (Integer) ss.get(nn);
0938:                                    if (i == null)
0939:                                        i = new Integer(0);
0940:                                    else
0941:                                        i = new Integer(i.intValue() + 1);
0942:                                    ss.put(nn, i);
0943:                                }
0944:                                stack.push(nn + "[" + i.toString() + "]");
0945:                                ++templateLevel;
0946:                                if (annon)
0947:                                    processTemplate(n2, ff);
0948:                                else
0949:                                    processTemplate(n2, null);
0950:                                --templateLevel;
0951:                                stack.pop();
0952:                            } else if (s.equals("field")
0953:                                    || s.equals("exclGroup")) {
0954:                                Node name = n2.getAttributes().getNamedItem(
0955:                                        "name");
0956:                                if (name != null) {
0957:                                    String nn = escapeSom(name.getNodeValue());
0958:                                    Integer i = (Integer) ff.get(nn);
0959:                                    if (i == null)
0960:                                        i = new Integer(0);
0961:                                    else
0962:                                        i = new Integer(i.intValue() + 1);
0963:                                    ff.put(nn, i);
0964:                                    stack.push(nn + "[" + i.toString() + "]");
0965:                                    String unstack = printStack();
0966:                                    order.add(unstack);
0967:                                    inverseSearchAdd(unstack);
0968:                                    name2Node.put(unstack, n2);
0969:                                    stack.pop();
0970:                                }
0971:                            } else if (!dynamicForm && templateLevel > 0
0972:                                    && s.equals("occur")) {
0973:                                int initial = 1;
0974:                                int min = 1;
0975:                                int max = 1;
0976:                                Node a = n2.getAttributes().getNamedItem(
0977:                                        "initial");
0978:                                if (a != null)
0979:                                    try {
0980:                                        initial = Integer.parseInt(a
0981:                                                .getNodeValue().trim());
0982:                                    } catch (Exception e) {
0983:                                    }
0984:                                a = n2.getAttributes().getNamedItem("min");
0985:                                if (a != null)
0986:                                    try {
0987:                                        min = Integer.parseInt(a.getNodeValue()
0988:                                                .trim());
0989:                                    } catch (Exception e) {
0990:                                    }
0991:                                a = n2.getAttributes().getNamedItem("max");
0992:                                if (a != null)
0993:                                    try {
0994:                                        max = Integer.parseInt(a.getNodeValue()
0995:                                                .trim());
0996:                                    } catch (Exception e) {
0997:                                    }
0998:                                if (initial != min || min != max)
0999:                                    dynamicForm = true;
1000:                            }
1001:                        }
1002:                        n2 = n2.getNextSibling();
1003:                    }
1004:                }
1005:
1006:                /**
1007:                 * <CODE>true</CODE> if it's a dynamic form; <CODE>false</CODE>
1008:                 * if it's a static form.
1009:                 * @return <CODE>true</CODE> if it's a dynamic form; <CODE>false</CODE>
1010:                 * if it's a static form
1011:                 */
1012:                public boolean isDynamicForm() {
1013:                    return dynamicForm;
1014:                }
1015:
1016:                /**
1017:                 * Sets the dynamic form flag. It doesn't change the template.
1018:                 * @param dynamicForm the dynamic form flag
1019:                 */
1020:                public void setDynamicForm(boolean dynamicForm) {
1021:                    this .dynamicForm = dynamicForm;
1022:                }
1023:            }
1024:
1025:            /**
1026:             * Gets the class that contains the template processing section of the XFA.
1027:             * @return the class that contains the template processing section of the XFA
1028:             */
1029:            public Xml2SomTemplate getTemplateSom() {
1030:                return templateSom;
1031:            }
1032:
1033:            /**
1034:             * Sets the class that contains the template processing section of the XFA
1035:             * @param templateSom the class that contains the template processing section of the XFA
1036:             */
1037:            public void setTemplateSom(Xml2SomTemplate templateSom) {
1038:                this .templateSom = templateSom;
1039:            }
1040:
1041:            /**
1042:             * Gets the class that contains the datasets processing section of the XFA.
1043:             * @return the class that contains the datasets processing section of the XFA
1044:             */
1045:            public Xml2SomDatasets getDatasetsSom() {
1046:                return datasetsSom;
1047:            }
1048:
1049:            /**
1050:             * Sets the class that contains the datasets processing section of the XFA.
1051:             * @param datasetsSom the class that contains the datasets processing section of the XFA
1052:             */
1053:            public void setDatasetsSom(Xml2SomDatasets datasetsSom) {
1054:                this .datasetsSom = datasetsSom;
1055:            }
1056:
1057:            /**
1058:             * Gets the class that contains the "classic" fields processing.
1059:             * @return the class that contains the "classic" fields processing
1060:             */
1061:            public AcroFieldsSearch getAcroFieldsSom() {
1062:                return acroFieldsSom;
1063:            }
1064:
1065:            /**
1066:             * Sets the class that contains the "classic" fields processing.
1067:             * @param acroFieldsSom the class that contains the "classic" fields processing
1068:             */
1069:            public void setAcroFieldsSom(AcroFieldsSearch acroFieldsSom) {
1070:                this .acroFieldsSom = acroFieldsSom;
1071:            }
1072:
1073:            /**
1074:             * Gets the <CODE>Node</CODE> that corresponds to the datasets part.
1075:             * @return the <CODE>Node</CODE> that corresponds to the datasets part
1076:             */
1077:            public Node getDatasetsNode() {
1078:                return datasetsNode;
1079:            }
1080:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.