Merge lp:~g-poussel/analysesi/devel into lp:analysesi

Proposed by Guillaume Poussel
Status: Needs review
Proposed branch: lp:~g-poussel/analysesi/devel
Merge into: lp:analysesi
Diff against target: 19746 lines (+19017/-0) (has conflicts)
95 files modified
.bzrignore (+4/-0)
.classpath (+10/-0)
.project (+17/-0)
.settings/org.eclipse.core.resources.prefs (+5/-0)
.settings/org.eclipse.core.runtime.prefs (+3/-0)
GPL.txt (+339/-0)
README (+13/-0)
cases/test-001.sql (+19/-0)
cases/test-002.sql (+19/-0)
cases/test-003.sql (+28/-0)
cases/test-004.sql (+37/-0)
cases/test-005.sql (+22/-0)
cases/test-006.sql (+22/-0)
cases/test-007.sql (+17/-0)
cases/test-008.sql (+23/-0)
cases/test-009.sql (+25/-0)
src/com/jgoodies/uif/lite/panel/SimpleInternalFrame.java (+534/-0)
src/com/microstar/xml/HandlerBase.java (+193/-0)
src/com/microstar/xml/XmlException.java (+99/-0)
src/com/microstar/xml/XmlHandler.java (+291/-0)
src/com/microstar/xml/XmlParser.java (+4312/-0)
src/langue/messages_ar.properties (+2/-0)
src/langue/messages_fr.properties (+197/-0)
src/org/analyse/core/gui/AboutWindow.java (+129/-0)
src/org/analyse/core/gui/AnalyseFrame.java (+340/-0)
src/org/analyse/core/gui/HtmlWindow.java (+131/-0)
src/org/analyse/core/gui/ParametrageWindow.java (+113/-0)
src/org/analyse/core/gui/SplashScreen.java (+82/-0)
src/org/analyse/core/gui/action/BasicAction.java (+82/-0)
src/org/analyse/core/gui/action/GlobalActionCollection.java (+214/-0)
src/org/analyse/core/gui/action/MainActionListener.java (+113/-0)
src/org/analyse/core/gui/action/NavigationActionFactory.java (+62/-0)
src/org/analyse/core/gui/menu/ClipboardPopupMenu.java (+68/-0)
src/org/analyse/core/gui/panel/HelpPanel.java (+237/-0)
src/org/analyse/core/gui/panel/Navigator.java (+109/-0)
src/org/analyse/core/gui/statusbar/AnalyseStatusbar.java (+79/-0)
src/org/analyse/core/gui/toolbar/AnalyseToolbar.java (+128/-0)
src/org/analyse/core/gui/zgraph/ZElement.java (+266/-0)
src/org/analyse/core/gui/zgraph/ZGraphique.java (+637/-0)
src/org/analyse/core/gui/zgraph/ZLien.java (+275/-0)
src/org/analyse/core/modules/AnalyseModule.java (+69/-0)
src/org/analyse/core/modules/AnalysePanel.java (+117/-0)
src/org/analyse/core/modules/ClipboardInterface.java (+30/-0)
src/org/analyse/core/modules/FilterModule.java (+44/-0)
src/org/analyse/core/modules/OpenModule.java (+31/-0)
src/org/analyse/core/modules/SaveModule.java (+33/-0)
src/org/analyse/core/modules/UndoInterface.java (+28/-0)
src/org/analyse/core/save/FiltreASI.java (+176/-0)
src/org/analyse/core/save/asi/ASIHandler.java (+92/-0)
src/org/analyse/core/save/asi/ASIModuleHandler.java (+40/-0)
src/org/analyse/core/save/asi/FilterASIModule.java (+42/-0)
src/org/analyse/core/util/Constantes.java (+90/-0)
src/org/analyse/core/util/GUIUtilities.java (+192/-0)
src/org/analyse/core/util/Memento.java (+26/-0)
src/org/analyse/core/util/MyBorderFactory.java (+34/-0)
src/org/analyse/core/util/MyPanelFactory.java (+75/-0)
src/org/analyse/core/util/Utilities.java (+98/-0)
src/org/analyse/core/util/save/AnalyseFilter.java (+85/-0)
src/org/analyse/core/util/save/AnalyseSave.java (+366/-0)
src/org/analyse/core/util/save/FileChooserFilter.java (+92/-0)
src/org/analyse/core/util/save/Open.java (+32/-0)
src/org/analyse/core/util/save/Save.java (+32/-0)
src/org/analyse/main/Main.java (+134/-0)
src/org/analyse/main/PlasticSettings.java (+262/-0)
src/org/analyse/main/help/GPL.html (+320/-0)
src/org/analyse/main/help/GPL.txt (+307/-0)
src/org/analyse/main/help/author.html (+29/-0)
src/org/analyse/main/help/whatsnew.html (+19/-0)
src/org/analyse/merise/gui/dialog/ConnectionDialog.java (+200/-0)
src/org/analyse/merise/gui/dialog/EntiteDialog.java (+533/-0)
src/org/analyse/merise/gui/dialog/LienDialog.java (+159/-0)
src/org/analyse/merise/gui/list/MeriseListModel.java (+116/-0)
src/org/analyse/merise/gui/panel/DictionnairePanel.java (+290/-0)
src/org/analyse/merise/gui/panel/MCDPanel.java (+598/-0)
src/org/analyse/merise/gui/panel/MLDPanel.java (+240/-0)
src/org/analyse/merise/gui/panel/MPDPanel.java (+228/-0)
src/org/analyse/merise/gui/panel/RapportPanel.java (+120/-0)
src/org/analyse/merise/gui/panel/SQLPanel.java (+362/-0)
src/org/analyse/merise/gui/table/ArgObserverTable.java (+73/-0)
src/org/analyse/merise/gui/table/DictionnaireTable.java (+451/-0)
src/org/analyse/merise/main/MeriseModule.java (+187/-0)
src/org/analyse/merise/mcd/composant/MCDAssociation.java (+128/-0)
src/org/analyse/merise/mcd/composant/MCDComponent.java (+852/-0)
src/org/analyse/merise/mcd/composant/MCDEntite.java (+132/-0)
src/org/analyse/merise/mcd/composant/MCDLien.java (+136/-0)
src/org/analyse/merise/mcd/composant/MCDObjet.java (+262/-0)
src/org/analyse/merise/mcd/composant/MLDCommand.java (+97/-0)
src/org/analyse/merise/mcd/composant/MLDComponent.java (+119/-0)
src/org/analyse/merise/mcd/composant/MPDComponent.java (+270/-0)
src/org/analyse/merise/mcd/composant/MPDEntite.java (+275/-0)
src/org/analyse/merise/mcd/composant/MPDLien.java (+151/-0)
src/org/analyse/merise/rapport/MeriseRapport.java (+212/-0)
src/org/analyse/merise/save/FiltreMeriseASI.java (+130/-0)
src/org/analyse/merise/save/asi/ASIMeriseHandler.java (+137/-0)
src/org/analyse/merise/sql/SQLCommand.java (+368/-0)
Conflict adding file .DS_Store.  Moved existing file to .DS_Store.moved.
Conflict adding file .bzrignore.  Moved existing file to .bzrignore.moved.
Conflict adding file .classpath.  Moved existing file to .classpath.moved.
Conflict adding file .project.  Moved existing file to .project.moved.
Conflict adding file .settings.  Moved existing file to .settings.moved.
Conflict adding file GPL.txt.  Moved existing file to GPL.txt.moved.
Conflict adding file README.  Moved existing file to README.moved.
Conflict adding file cases.  Moved existing file to cases.moved.
Conflict adding file lib.  Moved existing file to lib.moved.
Conflict adding file src.  Moved existing file to src.moved.
To merge this branch: bzr merge lp:~g-poussel/analysesi/devel
Reviewer Review Type Date Requested Status
Bruno Dabo Pending
Review via email: mp+85231@code.launchpad.net

Description of the change

Correction de bugs : dessin des relations ternaires (#370373), clic droit pendant le dessin (#692553)
Ajout des raccourcis claviers globaux (#700992, #666424)

To post a comment you must log in.
lp:~g-poussel/analysesi/devel updated
7. By Guillaume Poussel

Remove useless attributes and use enum instead of string constants.

8. By Guillaume Poussel

Huge cleanup, based on static code analysis.

9. By Guillaume Poussel

Cleaning up all Eclipse warnings: unused attributes and functions, version ID in Serializable classes.

10. By Guillaume Poussel

Bug fixes for class types in table model

11. By Guillaume Poussel

Remove commented out code

12. By Guillaume Poussel

Improving row adding with an empty row always at the bottom of the table

13. By Guillaume Poussel

Fix bug #712583: removing row in data dictionary is now working, even if table is sorted.

14. By Guillaume Poussel

Replace mouse button test with more semantic stuff.

15. By Guillaume Poussel

Organizing icons + fresh new icon set.

16. By Guillaume Poussel

Editing icon set.

17. By Guillaume Poussel

Side-effect from editing table model. Loops are now properly written.

18. By Guillaume Poussel

Smaller icons and text label improved.

19. By Guillaume Poussel

Remove almost all useless inner classes.

20. By Guillaume Poussel

Remove again a new useless inner classe.

21. By Guillaume Poussel

Fix bug and encoding in properties file.

22. By Guillaume Poussel

Buttons on navigator are now toggled on click.

23. By Guillaume Poussel

Cleanup constant and deprecated methods.

24. By Guillaume Poussel

Refactor i18n: remove useless constants, properties reordering…

25. By Guillaume Poussel

Cleanup Utilities class: removing useless methods, better name on translation function.

26. By Guillaume Poussel

Workspace cleanup.

27. By Guillaume Poussel

Trying to solve bug #848394. Let's see if it works!

28. By Guillaume Poussel

Get rid of uncovered code

29. By Guillaume Poussel

Fixing translation bug, and message arguments

30. By Guillaume Poussel

Better selection handling on moving dictionary rows

31. By Guillaume Poussel

Customize cursor when adding links and moving elements

32. By Guillaume Poussel

Again, properties file fixed.

33. By Guillaume Poussel

Remove static constants from main class.

34. By Guillaume Poussel

Few optimizations

35. By Guillaume Poussel

Remove all iterators loop, add Java 6 syntax

36. By Guillaume Poussel

GlobalActionCollection is now a singleton

37. By Guillaume Poussel

Huge cleanup: clear almost all warnings, remove useless comments (bug number are stored in commit messages)

38. By Guillaume Poussel

Remove all trailing whitespaces.

39. By Guillaume Poussel

Antialiasing on MLD/MCD

Unmerged revisions

39. By Guillaume Poussel

Antialiasing on MLD/MCD

38. By Guillaume Poussel

Remove all trailing whitespaces.

37. By Guillaume Poussel

Huge cleanup: clear almost all warnings, remove useless comments (bug number are stored in commit messages)

36. By Guillaume Poussel

GlobalActionCollection is now a singleton

35. By Guillaume Poussel

Remove all iterators loop, add Java 6 syntax

34. By Guillaume Poussel

Few optimizations

33. By Guillaume Poussel

Remove static constants from main class.

32. By Guillaume Poussel

Again, properties file fixed.

31. By Guillaume Poussel

Customize cursor when adding links and moving elements

30. By Guillaume Poussel

Better selection handling on moving dictionary rows

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file '.DS_Store'
2Binary files .DS_Store 1970-01-01 00:00:00 +0000 and .DS_Store 2011-12-27 11:11:23 +0000 differ
3=== renamed file '.DS_Store' => '.DS_Store.moved'
4=== added file '.bzrignore'
5--- .bzrignore 1970-01-01 00:00:00 +0000
6+++ .bzrignore 2011-12-27 11:11:23 +0000
7@@ -0,0 +1,4 @@
8+build
9+build/com
10+build/langue
11+build/org
12
13=== renamed file '.bzrignore' => '.bzrignore.moved'
14=== added file '.classpath'
15--- .classpath 1970-01-01 00:00:00 +0000
16+++ .classpath 2011-12-27 11:11:23 +0000
17@@ -0,0 +1,10 @@
18+<?xml version="1.0" encoding="UTF-8"?>
19+<classpath>
20+ <classpathentry kind="src" path="src"/>
21+ <classpathentry exported="true" kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
22+ <classpathentry exported="true" kind="lib" path="lib/looks-1.2.2.jar"/>
23+ <classpathentry exported="true" kind="lib" path="lib/forms-1.0.5.jar"/>
24+ <classpathentry exported="true" kind="lib" path="lib/mysql-connector-java-5.1.10-bin.jar"/>
25+ <classpathentry exported="true" kind="lib" path="lib/postgresql-8.4-701.jdbc4.jar"/>
26+ <classpathentry kind="output" path="build"/>
27+</classpath>
28
29=== renamed file '.classpath' => '.classpath.moved'
30=== added file '.project'
31--- .project 1970-01-01 00:00:00 +0000
32+++ .project 2011-12-27 11:11:23 +0000
33@@ -0,0 +1,17 @@
34+<?xml version="1.0" encoding="UTF-8"?>
35+<projectDescription>
36+ <name>AnalyseSI</name>
37+ <comment></comment>
38+ <projects>
39+ </projects>
40+ <buildSpec>
41+ <buildCommand>
42+ <name>org.eclipse.jdt.core.javabuilder</name>
43+ <arguments>
44+ </arguments>
45+ </buildCommand>
46+ </buildSpec>
47+ <natures>
48+ <nature>org.eclipse.jdt.core.javanature</nature>
49+ </natures>
50+</projectDescription>
51
52=== renamed file '.project' => '.project.moved'
53=== added directory '.settings'
54=== renamed directory '.settings' => '.settings.moved'
55=== added file '.settings/org.eclipse.core.resources.prefs'
56--- .settings/org.eclipse.core.resources.prefs 1970-01-01 00:00:00 +0000
57+++ .settings/org.eclipse.core.resources.prefs 2011-12-27 11:11:23 +0000
58@@ -0,0 +1,5 @@
59+#Wed Dec 29 22:26:40 CET 2010
60+eclipse.preferences.version=1
61+encoding//src/langue/messages_fr.properties=UTF-8
62+encoding/<project>=UTF-8
63+encoding/README=ISO-8859-1
64
65=== added file '.settings/org.eclipse.core.runtime.prefs'
66--- .settings/org.eclipse.core.runtime.prefs 1970-01-01 00:00:00 +0000
67+++ .settings/org.eclipse.core.runtime.prefs 2011-12-27 11:11:23 +0000
68@@ -0,0 +1,3 @@
69+#Sun Mar 02 00:15:18 GMT 2008
70+eclipse.preferences.version=1
71+line.separator=\n
72
73=== added file 'GPL.txt'
74--- GPL.txt 1970-01-01 00:00:00 +0000
75+++ GPL.txt 2011-12-27 11:11:23 +0000
76@@ -0,0 +1,339 @@
77+ GNU GENERAL PUBLIC LICENSE
78+ Version 2, June 1991
79+
80+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
81+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
82+ Everyone is permitted to copy and distribute verbatim copies
83+ of this license document, but changing it is not allowed.
84+
85+ Preamble
86+
87+ The licenses for most software are designed to take away your
88+freedom to share and change it. By contrast, the GNU General Public
89+License is intended to guarantee your freedom to share and change free
90+software--to make sure the software is free for all its users. This
91+General Public License applies to most of the Free Software
92+Foundation's software and to any other program whose authors commit to
93+using it. (Some other Free Software Foundation software is covered by
94+the GNU Lesser General Public License instead.) You can apply it to
95+your programs, too.
96+
97+ When we speak of free software, we are referring to freedom, not
98+price. Our General Public Licenses are designed to make sure that you
99+have the freedom to distribute copies of free software (and charge for
100+this service if you wish), that you receive source code or can get it
101+if you want it, that you can change the software or use pieces of it
102+in new free programs; and that you know you can do these things.
103+
104+ To protect your rights, we need to make restrictions that forbid
105+anyone to deny you these rights or to ask you to surrender the rights.
106+These restrictions translate to certain responsibilities for you if you
107+distribute copies of the software, or if you modify it.
108+
109+ For example, if you distribute copies of such a program, whether
110+gratis or for a fee, you must give the recipients all the rights that
111+you have. You must make sure that they, too, receive or can get the
112+source code. And you must show them these terms so they know their
113+rights.
114+
115+ We protect your rights with two steps: (1) copyright the software, and
116+(2) offer you this license which gives you legal permission to copy,
117+distribute and/or modify the software.
118+
119+ Also, for each author's protection and ours, we want to make certain
120+that everyone understands that there is no warranty for this free
121+software. If the software is modified by someone else and passed on, we
122+want its recipients to know that what they have is not the original, so
123+that any problems introduced by others will not reflect on the original
124+authors' reputations.
125+
126+ Finally, any free program is threatened constantly by software
127+patents. We wish to avoid the danger that redistributors of a free
128+program will individually obtain patent licenses, in effect making the
129+program proprietary. To prevent this, we have made it clear that any
130+patent must be licensed for everyone's free use or not licensed at all.
131+
132+ The precise terms and conditions for copying, distribution and
133+modification follow.
134+
135+ GNU GENERAL PUBLIC LICENSE
136+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
137+
138+ 0. This License applies to any program or other work which contains
139+a notice placed by the copyright holder saying it may be distributed
140+under the terms of this General Public License. The "Program", below,
141+refers to any such program or work, and a "work based on the Program"
142+means either the Program or any derivative work under copyright law:
143+that is to say, a work containing the Program or a portion of it,
144+either verbatim or with modifications and/or translated into another
145+language. (Hereinafter, translation is included without limitation in
146+the term "modification".) Each licensee is addressed as "you".
147+
148+Activities other than copying, distribution and modification are not
149+covered by this License; they are outside its scope. The act of
150+running the Program is not restricted, and the output from the Program
151+is covered only if its contents constitute a work based on the
152+Program (independent of having been made by running the Program).
153+Whether that is true depends on what the Program does.
154+
155+ 1. You may copy and distribute verbatim copies of the Program's
156+source code as you receive it, in any medium, provided that you
157+conspicuously and appropriately publish on each copy an appropriate
158+copyright notice and disclaimer of warranty; keep intact all the
159+notices that refer to this License and to the absence of any warranty;
160+and give any other recipients of the Program a copy of this License
161+along with the Program.
162+
163+You may charge a fee for the physical act of transferring a copy, and
164+you may at your option offer warranty protection in exchange for a fee.
165+
166+ 2. You may modify your copy or copies of the Program or any portion
167+of it, thus forming a work based on the Program, and copy and
168+distribute such modifications or work under the terms of Section 1
169+above, provided that you also meet all of these conditions:
170+
171+ a) You must cause the modified files to carry prominent notices
172+ stating that you changed the files and the date of any change.
173+
174+ b) You must cause any work that you distribute or publish, that in
175+ whole or in part contains or is derived from the Program or any
176+ part thereof, to be licensed as a whole at no charge to all third
177+ parties under the terms of this License.
178+
179+ c) If the modified program normally reads commands interactively
180+ when run, you must cause it, when started running for such
181+ interactive use in the most ordinary way, to print or display an
182+ announcement including an appropriate copyright notice and a
183+ notice that there is no warranty (or else, saying that you provide
184+ a warranty) and that users may redistribute the program under
185+ these conditions, and telling the user how to view a copy of this
186+ License. (Exception: if the Program itself is interactive but
187+ does not normally print such an announcement, your work based on
188+ the Program is not required to print an announcement.)
189+
190+These requirements apply to the modified work as a whole. If
191+identifiable sections of that work are not derived from the Program,
192+and can be reasonably considered independent and separate works in
193+themselves, then this License, and its terms, do not apply to those
194+sections when you distribute them as separate works. But when you
195+distribute the same sections as part of a whole which is a work based
196+on the Program, the distribution of the whole must be on the terms of
197+this License, whose permissions for other licensees extend to the
198+entire whole, and thus to each and every part regardless of who wrote it.
199+
200+Thus, it is not the intent of this section to claim rights or contest
201+your rights to work written entirely by you; rather, the intent is to
202+exercise the right to control the distribution of derivative or
203+collective works based on the Program.
204+
205+In addition, mere aggregation of another work not based on the Program
206+with the Program (or with a work based on the Program) on a volume of
207+a storage or distribution medium does not bring the other work under
208+the scope of this License.
209+
210+ 3. You may copy and distribute the Program (or a work based on it,
211+under Section 2) in object code or executable form under the terms of
212+Sections 1 and 2 above provided that you also do one of the following:
213+
214+ a) Accompany it with the complete corresponding machine-readable
215+ source code, which must be distributed under the terms of Sections
216+ 1 and 2 above on a medium customarily used for software interchange; or,
217+
218+ b) Accompany it with a written offer, valid for at least three
219+ years, to give any third party, for a charge no more than your
220+ cost of physically performing source distribution, a complete
221+ machine-readable copy of the corresponding source code, to be
222+ distributed under the terms of Sections 1 and 2 above on a medium
223+ customarily used for software interchange; or,
224+
225+ c) Accompany it with the information you received as to the offer
226+ to distribute corresponding source code. (This alternative is
227+ allowed only for noncommercial distribution and only if you
228+ received the program in object code or executable form with such
229+ an offer, in accord with Subsection b above.)
230+
231+The source code for a work means the preferred form of the work for
232+making modifications to it. For an executable work, complete source
233+code means all the source code for all modules it contains, plus any
234+associated interface definition files, plus the scripts used to
235+control compilation and installation of the executable. However, as a
236+special exception, the source code distributed need not include
237+anything that is normally distributed (in either source or binary
238+form) with the major components (compiler, kernel, and so on) of the
239+operating system on which the executable runs, unless that component
240+itself accompanies the executable.
241+
242+If distribution of executable or object code is made by offering
243+access to copy from a designated place, then offering equivalent
244+access to copy the source code from the same place counts as
245+distribution of the source code, even though third parties are not
246+compelled to copy the source along with the object code.
247+
248+ 4. You may not copy, modify, sublicense, or distribute the Program
249+except as expressly provided under this License. Any attempt
250+otherwise to copy, modify, sublicense or distribute the Program is
251+void, and will automatically terminate your rights under this License.
252+However, parties who have received copies, or rights, from you under
253+this License will not have their licenses terminated so long as such
254+parties remain in full compliance.
255+
256+ 5. You are not required to accept this License, since you have not
257+signed it. However, nothing else grants you permission to modify or
258+distribute the Program or its derivative works. These actions are
259+prohibited by law if you do not accept this License. Therefore, by
260+modifying or distributing the Program (or any work based on the
261+Program), you indicate your acceptance of this License to do so, and
262+all its terms and conditions for copying, distributing or modifying
263+the Program or works based on it.
264+
265+ 6. Each time you redistribute the Program (or any work based on the
266+Program), the recipient automatically receives a license from the
267+original licensor to copy, distribute or modify the Program subject to
268+these terms and conditions. You may not impose any further
269+restrictions on the recipients' exercise of the rights granted herein.
270+You are not responsible for enforcing compliance by third parties to
271+this License.
272+
273+ 7. If, as a consequence of a court judgment or allegation of patent
274+infringement or for any other reason (not limited to patent issues),
275+conditions are imposed on you (whether by court order, agreement or
276+otherwise) that contradict the conditions of this License, they do not
277+excuse you from the conditions of this License. If you cannot
278+distribute so as to satisfy simultaneously your obligations under this
279+License and any other pertinent obligations, then as a consequence you
280+may not distribute the Program at all. For example, if a patent
281+license would not permit royalty-free redistribution of the Program by
282+all those who receive copies directly or indirectly through you, then
283+the only way you could satisfy both it and this License would be to
284+refrain entirely from distribution of the Program.
285+
286+If any portion of this section is held invalid or unenforceable under
287+any particular circumstance, the balance of the section is intended to
288+apply and the section as a whole is intended to apply in other
289+circumstances.
290+
291+It is not the purpose of this section to induce you to infringe any
292+patents or other property right claims or to contest validity of any
293+such claims; this section has the sole purpose of protecting the
294+integrity of the free software distribution system, which is
295+implemented by public license practices. Many people have made
296+generous contributions to the wide range of software distributed
297+through that system in reliance on consistent application of that
298+system; it is up to the author/donor to decide if he or she is willing
299+to distribute software through any other system and a licensee cannot
300+impose that choice.
301+
302+This section is intended to make thoroughly clear what is believed to
303+be a consequence of the rest of this License.
304+
305+ 8. If the distribution and/or use of the Program is restricted in
306+certain countries either by patents or by copyrighted interfaces, the
307+original copyright holder who places the Program under this License
308+may add an explicit geographical distribution limitation excluding
309+those countries, so that distribution is permitted only in or among
310+countries not thus excluded. In such case, this License incorporates
311+the limitation as if written in the body of this License.
312+
313+ 9. The Free Software Foundation may publish revised and/or new versions
314+of the General Public License from time to time. Such new versions will
315+be similar in spirit to the present version, but may differ in detail to
316+address new problems or concerns.
317+
318+Each version is given a distinguishing version number. If the Program
319+specifies a version number of this License which applies to it and "any
320+later version", you have the option of following the terms and conditions
321+either of that version or of any later version published by the Free
322+Software Foundation. If the Program does not specify a version number of
323+this License, you may choose any version ever published by the Free Software
324+Foundation.
325+
326+ 10. If you wish to incorporate parts of the Program into other free
327+programs whose distribution conditions are different, write to the author
328+to ask for permission. For software which is copyrighted by the Free
329+Software Foundation, write to the Free Software Foundation; we sometimes
330+make exceptions for this. Our decision will be guided by the two goals
331+of preserving the free status of all derivatives of our free software and
332+of promoting the sharing and reuse of software generally.
333+
334+ NO WARRANTY
335+
336+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
337+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
338+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
339+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
340+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
341+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
342+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
343+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
344+REPAIR OR CORRECTION.
345+
346+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
347+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
348+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
349+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
350+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
351+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
352+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
353+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
354+POSSIBILITY OF SUCH DAMAGES.
355+
356+ END OF TERMS AND CONDITIONS
357+
358+ How to Apply These Terms to Your New Programs
359+
360+ If you develop a new program, and you want it to be of the greatest
361+possible use to the public, the best way to achieve this is to make it
362+free software which everyone can redistribute and change under these terms.
363+
364+ To do so, attach the following notices to the program. It is safest
365+to attach them to the start of each source file to most effectively
366+convey the exclusion of warranty; and each file should have at least
367+the "copyright" line and a pointer to where the full notice is found.
368+
369+ <one line to give the program's name and a brief idea of what it does.>
370+ Copyright (C) <year> <name of author>
371+
372+ This program is free software; you can redistribute it and/or modify
373+ it under the terms of the GNU General Public License as published by
374+ the Free Software Foundation; either version 2 of the License, or
375+ (at your option) any later version.
376+
377+ This program is distributed in the hope that it will be useful,
378+ but WITHOUT ANY WARRANTY; without even the implied warranty of
379+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
380+ GNU General Public License for more details.
381+
382+ You should have received a copy of the GNU General Public License along
383+ with this program; if not, write to the Free Software Foundation, Inc.,
384+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
385+
386+Also add information on how to contact you by electronic and paper mail.
387+
388+If the program is interactive, make it output a short notice like this
389+when it starts in an interactive mode:
390+
391+ Gnomovision version 69, Copyright (C) year name of author
392+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
393+ This is free software, and you are welcome to redistribute it
394+ under certain conditions; type `show c' for details.
395+
396+The hypothetical commands `show w' and `show c' should show the appropriate
397+parts of the General Public License. Of course, the commands you use may
398+be called something other than `show w' and `show c'; they could even be
399+mouse-clicks or menu items--whatever suits your program.
400+
401+You should also get your employer (if you work as a programmer) or your
402+school, if any, to sign a "copyright disclaimer" for the program, if
403+necessary. Here is a sample; alter the names:
404+
405+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
406+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
407+
408+ <signature of Ty Coon>, 1 April 1989
409+ Ty Coon, President of Vice
410+
411+This General Public License does not permit incorporating your program into
412+proprietary programs. If your program is a subroutine library, you may
413+consider it more useful to permit linking proprietary applications with the
414+library. If this is what you want to do, use the GNU Lesser General
415+Public License instead of this License.
416
417=== renamed file 'GPL.txt' => 'GPL.txt.moved'
418=== added file 'README'
419--- README 1970-01-01 00:00:00 +0000
420+++ README 2011-12-27 11:11:23 +0000
421@@ -0,0 +1,13 @@
422+Auteur : Bruno Dabo
423+
424+Le projet est hébergé sur https://launchpad.net/analysesi
425+N'hésitez pas à participer au groupe AnalyseSI ( https://launchpad.net/~analysesi )
426+Une mailing-list est ouverte sur analysesi@lists.launchpad.net
427+
428+----------------------
429+Corrections apportées
430+RELEASE : 0.75 ( Rockhampton )
431+Date : janvier 2011
432+----------------------
433+#505822 Utiliser l'outil curseur par défaut dans la vue MCD
434+#517141 Ajouter le modèle MLDR
435
436=== renamed file 'README' => 'README.moved'
437=== added directory 'cases'
438=== renamed directory 'cases' => 'cases.moved'
439=== added file 'cases/.DS_Store'
440Binary files cases/.DS_Store 1970-01-01 00:00:00 +0000 and cases/.DS_Store 2011-12-27 11:11:23 +0000 differ
441=== added file 'cases/test-001.asi'
442Binary files cases/test-001.asi 1970-01-01 00:00:00 +0000 and cases/test-001.asi 2011-12-27 11:11:23 +0000 differ
443=== added file 'cases/test-001.png'
444Binary files cases/test-001.png 1970-01-01 00:00:00 +0000 and cases/test-001.png 2011-12-27 11:11:23 +0000 differ
445=== added file 'cases/test-001.sql'
446--- cases/test-001.sql 1970-01-01 00:00:00 +0000
447+++ cases/test-001.sql 2011-12-27 11:11:23 +0000
448@@ -0,0 +1,19 @@
449+# script créé le : Thu Dec 23 15:22:52 CET 2010 ;
450+
451+# use VOTRE_BASE_DE_DONNEE ;
452+
453+DROP TABLE IF EXISTS SOCIETE ;
454+
455+CREATE TABLE SOCIETE (id_societe INT NOT NULL,
456+nom_societe VARCHAR(30),
457+PRIMARY KEY (id_societe) ) ENGINE=InnoDB;
458+
459+DROP TABLE IF EXISTS EMPLOYE ;
460+
461+CREATE TABLE EMPLOYE (id_employe INT NOT NULL,
462+nom_employe VARCHAR(30),
463+id_societe INT,
464+PRIMARY KEY (id_employe) ) ENGINE=InnoDB;
465+
466+ALTER TABLE EMPLOYE ADD CONSTRAINT FK_EMPLOYE_id_societe FOREIGN KEY (id_societe) REFERENCES SOCIETE (id_societe);
467+
468
469=== added file 'cases/test-002.asi'
470Binary files cases/test-002.asi 1970-01-01 00:00:00 +0000 and cases/test-002.asi 2011-12-27 11:11:23 +0000 differ
471=== added file 'cases/test-002.png'
472Binary files cases/test-002.png 1970-01-01 00:00:00 +0000 and cases/test-002.png 2011-12-27 11:11:23 +0000 differ
473=== added file 'cases/test-002.sql'
474--- cases/test-002.sql 1970-01-01 00:00:00 +0000
475+++ cases/test-002.sql 2011-12-27 11:11:23 +0000
476@@ -0,0 +1,19 @@
477+# script créé le : Thu Dec 23 15:23:06 CET 2010 ;
478+
479+# use VOTRE_BASE_DE_DONNEE ;
480+
481+DROP TABLE IF EXISTS SOCIETE ;
482+
483+CREATE TABLE SOCIETE (id_societe INT NOT NULL,
484+nom_societe VARCHAR(30),
485+PRIMARY KEY (id_societe) ) ENGINE=InnoDB;
486+
487+DROP TABLE IF EXISTS EMPLOYE ;
488+
489+CREATE TABLE EMPLOYE (id_employe INT NOT NULL,
490+nom_employe VARCHAR(30),
491+id_societe INT NOT NULL,
492+PRIMARY KEY (id_employe) ) ENGINE=InnoDB;
493+
494+ALTER TABLE EMPLOYE ADD CONSTRAINT FK_EMPLOYE_id_societe FOREIGN KEY (id_societe) REFERENCES SOCIETE (id_societe);
495+
496
497=== added file 'cases/test-003.asi'
498Binary files cases/test-003.asi 1970-01-01 00:00:00 +0000 and cases/test-003.asi 2011-12-27 11:11:23 +0000 differ
499=== added file 'cases/test-003.png'
500Binary files cases/test-003.png 1970-01-01 00:00:00 +0000 and cases/test-003.png 2011-12-27 11:11:23 +0000 differ
501=== added file 'cases/test-003.sql'
502--- cases/test-003.sql 1970-01-01 00:00:00 +0000
503+++ cases/test-003.sql 2011-12-27 11:11:23 +0000
504@@ -0,0 +1,28 @@
505+# script créé le : Thu Dec 23 15:23:26 CET 2010 ;
506+
507+# use VOTRE_BASE_DE_DONNEE ;
508+
509+DROP TABLE IF EXISTS COMMANDE ;
510+
511+CREATE TABLE COMMANDE (id_commande INT NOT NULL,
512+date_commande DATETIME,
513+PRIMARY KEY (id_commande) ) ENGINE=InnoDB;
514+
515+DROP TABLE IF EXISTS PRODUIT ;
516+
517+CREATE TABLE PRODUIT (id_produit INT NOT NULL,
518+libelle_produit VARCHAR(30),
519+PRIMARY KEY (id_produit) ) ENGINE=InnoDB;
520+
521+DROP TABLE IF EXISTS compose ;
522+
523+CREATE TABLE compose (id_commande INT NOT NULL,
524+id_produit INT NOT NULL,
525+quantite INT,
526+PRIMARY KEY (id_commande,
527+ id_produit) ) ENGINE=InnoDB;
528+
529+ALTER TABLE compose ADD CONSTRAINT FK_compose_id_commande FOREIGN KEY (id_commande) REFERENCES COMMANDE (id_commande);
530+
531+ALTER TABLE compose ADD CONSTRAINT FK_compose_id_produit FOREIGN KEY (id_produit) REFERENCES PRODUIT (id_produit);
532+
533
534=== added file 'cases/test-004.asi'
535Binary files cases/test-004.asi 1970-01-01 00:00:00 +0000 and cases/test-004.asi 2011-12-27 11:11:23 +0000 differ
536=== added file 'cases/test-004.png'
537Binary files cases/test-004.png 1970-01-01 00:00:00 +0000 and cases/test-004.png 2011-12-27 11:11:23 +0000 differ
538=== added file 'cases/test-004.sql'
539--- cases/test-004.sql 1970-01-01 00:00:00 +0000
540+++ cases/test-004.sql 2011-12-27 11:11:23 +0000
541@@ -0,0 +1,37 @@
542+# script créé le : Thu Dec 23 15:16:07 CET 2010 ;
543+
544+# use VOTRE_BASE_DE_DONNEE ;
545+
546+DROP TABLE IF EXISTS ETUDIANT ;
547+
548+CREATE TABLE ETUDIANT (id_etudiant INT NOT NULL,
549+nom_etudiant VARCHAR(30),
550+PRIMARY KEY (id_etudiant) ) ENGINE=InnoDB;
551+
552+DROP TABLE IF EXISTS LANGUE ;
553+
554+CREATE TABLE LANGUE (id_langue INT NOT NULL,
555+nom_langue VARCHAR(30),
556+PRIMARY KEY (id_langue) ) ENGINE=InnoDB;
557+
558+DROP TABLE IF EXISTS NIVEAU ;
559+
560+CREATE TABLE NIVEAU (id_niveau INT NOT NULL,
561+nom_niveau VARCHAR(30),
562+PRIMARY KEY (id_niveau) ) ENGINE=InnoDB;
563+
564+DROP TABLE IF EXISTS parle ;
565+
566+CREATE TABLE parle (id_etudiant INT NOT NULL,
567+id_langue INT NOT NULL,
568+id_niveau INT NOT NULL,
569+PRIMARY KEY (id_etudiant,
570+ id_langue,
571+ id_niveau) ) ENGINE=InnoDB;
572+
573+ALTER TABLE parle ADD CONSTRAINT FK_parle_id_etudiant FOREIGN KEY (id_etudiant) REFERENCES ETUDIANT (id_etudiant);
574+
575+ALTER TABLE parle ADD CONSTRAINT FK_parle_id_langue FOREIGN KEY (id_langue) REFERENCES LANGUE (id_langue);
576+
577+ALTER TABLE parle ADD CONSTRAINT FK_parle_id_niveau FOREIGN KEY (id_niveau) REFERENCES NIVEAU (id_niveau);
578+
579
580=== added file 'cases/test-005.asi'
581Binary files cases/test-005.asi 1970-01-01 00:00:00 +0000 and cases/test-005.asi 2011-12-27 11:11:23 +0000 differ
582=== added file 'cases/test-005.png'
583Binary files cases/test-005.png 1970-01-01 00:00:00 +0000 and cases/test-005.png 2011-12-27 11:11:23 +0000 differ
584=== added file 'cases/test-005.sql'
585--- cases/test-005.sql 1970-01-01 00:00:00 +0000
586+++ cases/test-005.sql 2011-12-27 11:11:23 +0000
587@@ -0,0 +1,22 @@
588+# script créé le : Thu Dec 23 15:23:44 CET 2010 ;
589+
590+# use VOTRE_BASE_DE_DONNEE ;
591+
592+DROP TABLE IF EXISTS ANIMATEUR ;
593+
594+CREATE TABLE ANIMATEUR (id_animateur INT NOT NULL,
595+nom_animateur VARCHAR(30),
596+id_groupe INT,
597+PRIMARY KEY (id_animateur) ) ENGINE=InnoDB;
598+
599+DROP TABLE IF EXISTS GROUPE ;
600+
601+CREATE TABLE GROUPE (id_groupe INT NOT NULL,
602+nom_groupe VARCHAR(30),
603+id_animateur INT,
604+PRIMARY KEY (id_groupe) ) ENGINE=InnoDB;
605+
606+ALTER TABLE ANIMATEUR ADD CONSTRAINT FK_ANIMATEUR_id_groupe FOREIGN KEY (id_groupe) REFERENCES GROUPE (id_groupe);
607+
608+ALTER TABLE GROUPE ADD CONSTRAINT FK_GROUPE_id_animateur FOREIGN KEY (id_animateur) REFERENCES ANIMATEUR (id_animateur);
609+
610
611=== added file 'cases/test-006.asi'
612Binary files cases/test-006.asi 1970-01-01 00:00:00 +0000 and cases/test-006.asi 2011-12-27 11:11:23 +0000 differ
613=== added file 'cases/test-006.png'
614Binary files cases/test-006.png 1970-01-01 00:00:00 +0000 and cases/test-006.png 2011-12-27 11:11:23 +0000 differ
615=== added file 'cases/test-006.sql'
616--- cases/test-006.sql 1970-01-01 00:00:00 +0000
617+++ cases/test-006.sql 2011-12-27 11:11:23 +0000
618@@ -0,0 +1,22 @@
619+# script créé le : Thu Dec 23 15:24:35 CET 2010 ;
620+
621+# use VOTRE_BASE_DE_DONNEE ;
622+
623+DROP TABLE IF EXISTS ANIMATEUR ;
624+
625+CREATE TABLE ANIMATEUR (id_animateur INT NOT NULL,
626+nom_animateur VARCHAR(30),
627+id_groupe INT,
628+PRIMARY KEY (id_animateur) ) ENGINE=InnoDB;
629+
630+DROP TABLE IF EXISTS GROUPE ;
631+
632+CREATE TABLE GROUPE (id_groupe INT NOT NULL,
633+nom_groupe VARCHAR(30),
634+id_animateur INT,
635+PRIMARY KEY (id_groupe) ) ENGINE=InnoDB;
636+
637+ALTER TABLE ANIMATEUR ADD CONSTRAINT FK_ANIMATEUR_id_groupe FOREIGN KEY (id_groupe) REFERENCES GROUPE (id_groupe);
638+
639+ALTER TABLE GROUPE ADD CONSTRAINT FK_GROUPE_id_animateur FOREIGN KEY (id_animateur) REFERENCES ANIMATEUR (id_animateur);
640+
641
642=== added file 'cases/test-007.asi'
643Binary files cases/test-007.asi 1970-01-01 00:00:00 +0000 and cases/test-007.asi 2011-12-27 11:11:23 +0000 differ
644=== added file 'cases/test-007.png'
645Binary files cases/test-007.png 1970-01-01 00:00:00 +0000 and cases/test-007.png 2011-12-27 11:11:23 +0000 differ
646=== added file 'cases/test-007.sql'
647--- cases/test-007.sql 1970-01-01 00:00:00 +0000
648+++ cases/test-007.sql 2011-12-27 11:11:23 +0000
649@@ -0,0 +1,17 @@
650+# script créé le : Thu Dec 23 15:24:52 CET 2010 ;
651+
652+# use VOTRE_BASE_DE_DONNEE ;
653+
654+DROP TABLE IF EXISTS A ;
655+
656+CREATE TABLE A (id_a BIGINT NOT NULL,
657+PRIMARY KEY (id_a) ) ENGINE=InnoDB;
658+
659+DROP TABLE IF EXISTS B ;
660+
661+CREATE TABLE B (id_b BIGINT NOT NULL,
662+id_a BIGINT,
663+PRIMARY KEY (id_b) ) ENGINE=InnoDB;
664+
665+ALTER TABLE B ADD CONSTRAINT FK_B_id_a FOREIGN KEY (id_a) REFERENCES A (id_a);
666+
667
668=== added file 'cases/test-008.asi'
669Binary files cases/test-008.asi 1970-01-01 00:00:00 +0000 and cases/test-008.asi 2011-12-27 11:11:23 +0000 differ
670=== added file 'cases/test-008.png'
671Binary files cases/test-008.png 1970-01-01 00:00:00 +0000 and cases/test-008.png 2011-12-27 11:11:23 +0000 differ
672=== added file 'cases/test-008.sql'
673--- cases/test-008.sql 1970-01-01 00:00:00 +0000
674+++ cases/test-008.sql 2011-12-27 11:11:23 +0000
675@@ -0,0 +1,23 @@
676+# script créé le : Thu Dec 23 15:25:20 CET 2010 ;
677+
678+# use VOTRE_BASE_DE_DONNEE ;
679+
680+DROP TABLE IF EXISTS E1 ;
681+
682+CREATE TABLE E1 (id_E1 BIGINT NOT NULL,
683+PRIMARY KEY (id_E1) ) ENGINE=InnoDB;
684+
685+DROP TABLE IF EXISTS E2 ;
686+
687+CREATE TABLE E2 (id_E2 BIGINT NOT NULL,
688+id_E1 BIGINT NOT NULL,
689+id_E1_a2 BIGINT NOT NULL,
690+id_E1_a3 BIGINT NOT NULL,
691+PRIMARY KEY (id_E2) ) ENGINE=InnoDB;
692+
693+ALTER TABLE E2 ADD CONSTRAINT FK_E2_id_E1 FOREIGN KEY (id_E1) REFERENCES E1 (id_E1);
694+
695+ALTER TABLE E2 ADD CONSTRAINT FK_E2_id_E1_a2 FOREIGN KEY (id_E1_a2) REFERENCES E1 (id_E1);
696+
697+ALTER TABLE E2 ADD CONSTRAINT FK_E2_id_E1_a3 FOREIGN KEY (id_E1_a3) REFERENCES E1 (id_E1);
698+
699
700=== added file 'cases/test-009.asi'
701Binary files cases/test-009.asi 1970-01-01 00:00:00 +0000 and cases/test-009.asi 2011-12-27 11:11:23 +0000 differ
702=== added file 'cases/test-009.png'
703Binary files cases/test-009.png 1970-01-01 00:00:00 +0000 and cases/test-009.png 2011-12-27 11:11:23 +0000 differ
704=== added file 'cases/test-009.sql'
705--- cases/test-009.sql 1970-01-01 00:00:00 +0000
706+++ cases/test-009.sql 2011-12-27 11:11:23 +0000
707@@ -0,0 +1,25 @@
708+# script créé le : Thu Dec 23 15:26:48 CET 2010 ;
709+
710+# use VOTRE_BASE_DE_DONNEE ;
711+
712+DROP TABLE IF EXISTS a ;
713+
714+CREATE TABLE a (id_a int AUTO_INCREMENT NOT NULL,
715+id_c int NOT NULL,
716+PRIMARY KEY (id_a) ) ENGINE=InnoDB;
717+
718+DROP TABLE IF EXISTS b ;
719+
720+CREATE TABLE b (id_b int AUTO_INCREMENT NOT NULL,
721+id_a int NOT NULL,
722+PRIMARY KEY (id_b) ) ENGINE=InnoDB;
723+
724+DROP TABLE IF EXISTS c ;
725+
726+CREATE TABLE c (id_c int AUTO_INCREMENT NOT NULL,
727+PRIMARY KEY (id_c) ) ENGINE=InnoDB;
728+
729+ALTER TABLE a ADD CONSTRAINT FK_a_id_c FOREIGN KEY (id_c) REFERENCES c (id_c);
730+
731+ALTER TABLE b ADD CONSTRAINT FK_b_id_a FOREIGN KEY (id_a) REFERENCES a (id_a);
732+
733
734=== added directory 'lib'
735=== renamed directory 'lib' => 'lib.moved'
736=== added file 'lib/forms-1.0.5.jar'
737Binary files lib/forms-1.0.5.jar 1970-01-01 00:00:00 +0000 and lib/forms-1.0.5.jar 2011-12-27 11:11:23 +0000 differ
738=== added file 'lib/looks-1.2.2.jar'
739Binary files lib/looks-1.2.2.jar 1970-01-01 00:00:00 +0000 and lib/looks-1.2.2.jar 2011-12-27 11:11:23 +0000 differ
740=== added file 'lib/mysql-connector-java-5.1.10-bin.jar'
741Binary files lib/mysql-connector-java-5.1.10-bin.jar 1970-01-01 00:00:00 +0000 and lib/mysql-connector-java-5.1.10-bin.jar 2011-12-27 11:11:23 +0000 differ
742=== added file 'lib/postgresql-8.4-701.jdbc4.jar'
743Binary files lib/postgresql-8.4-701.jdbc4.jar 1970-01-01 00:00:00 +0000 and lib/postgresql-8.4-701.jdbc4.jar 2011-12-27 11:11:23 +0000 differ
744=== added directory 'src'
745=== renamed directory 'src' => 'src.moved'
746=== added file 'src/.DS_Store'
747Binary files src/.DS_Store 1970-01-01 00:00:00 +0000 and src/.DS_Store 2011-12-27 11:11:23 +0000 differ
748=== added directory 'src/com'
749=== added directory 'src/com/jgoodies'
750=== added directory 'src/com/jgoodies/uif'
751=== added directory 'src/com/jgoodies/uif/lite'
752=== added directory 'src/com/jgoodies/uif/lite/panel'
753=== added file 'src/com/jgoodies/uif/lite/panel/SimpleInternalFrame.java'
754--- src/com/jgoodies/uif/lite/panel/SimpleInternalFrame.java 1970-01-01 00:00:00 +0000
755+++ src/com/jgoodies/uif/lite/panel/SimpleInternalFrame.java 2011-12-27 11:11:23 +0000
756@@ -0,0 +1,534 @@
757+/*
758+ * Copyright (c) 2003 JGoodies Karsten Lentzsch. All Rights Reserved.
759+ *
760+ * Redistribution and use in source and binary forms, with or without
761+ * modification, are permitted provided that the following conditions are met:
762+ *
763+ * o Redistributions of source code must retain the above copyright notice,
764+ * this list of conditions and the following disclaimer.
765+ *
766+ * o Redistributions in binary form must reproduce the above copyright notice,
767+ * this list of conditions and the following disclaimer in the documentation
768+ * and/or other materials provided with the distribution.
769+ *
770+ * o Neither the name of JGoodies Karsten Lentzsch nor the names of
771+ * its contributors may be used to endorse or promote products derived
772+ * from this software without specific prior written permission.
773+ *
774+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
775+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
776+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
777+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
778+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
779+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
780+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
781+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
782+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
783+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
784+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
785+ */
786+
787+package com.jgoodies.uif.lite.panel;
788+
789+import java.awt.BorderLayout;
790+import java.awt.Color;
791+import java.awt.Component;
792+import java.awt.GradientPaint;
793+import java.awt.Graphics;
794+import java.awt.Graphics2D;
795+import java.awt.Insets;
796+import java.awt.LayoutManager;
797+import java.awt.Paint;
798+
799+import javax.swing.BorderFactory;
800+import javax.swing.Icon;
801+import javax.swing.JComponent;
802+import javax.swing.JLabel;
803+import javax.swing.JPanel;
804+import javax.swing.JToolBar;
805+import javax.swing.SwingConstants;
806+import javax.swing.UIManager;
807+import javax.swing.border.AbstractBorder;
808+
809+import com.jgoodies.plaf.LookUtils;
810+
811+/**
812+ * A <code>JPanel</code> subclass that has a drop shadow border and that
813+ * provides a header with icon, title and tool bar.
814+ * <p>
815+ *
816+ * This class can be used to replace the <code>JInternalFrame</code>, for use
817+ * outside of a <code>JDesktopPane</code>. The
818+ * <code>SimpleInternalFrame</code> is less flexible but often more usable; it
819+ * avoids overlapping windows and scales well up to IDE size. Several customers
820+ * have reported that they and their clients feel much better with both the
821+ * appearance and the UI feel.
822+ * <p>
823+ *
824+ * The SimpleInternalFrame provides the following bound properties:
825+ * <i>frameIcon, title, toolBar, content, selected. </i>
826+ * <p>
827+ *
828+ * By default the SimpleInternalFrame is in <i>selected </i> state. If you don't
829+ * do anything, multiple simple internal frames will be displayed as selected.
830+ *
831+ * @author Karsten Lentzsch
832+ * @version $Revision: 1.1 $
833+ *
834+ * @see javax.swing.JInternalFrame
835+ * @see javax.swing.JDesktopPane
836+ */
837+
838+public class SimpleInternalFrame extends JPanel
839+{
840+
841+ /**
842+ *
843+ */
844+ private static final long serialVersionUID = 6209018648321926386L;
845+
846+ private JLabel titleLabel;
847+
848+ private GradientPanel gradientPanel;
849+
850+ private JPanel headerPanel;
851+
852+ private boolean isSelected;
853+
854+ // Instance Creation ****************************************************
855+
856+ /**
857+ * Constructs a <code>SimpleInternalFrame</code> with the specified title.
858+ *
859+ * @param title
860+ * the initial title
861+ */
862+ public SimpleInternalFrame(String title)
863+ {
864+ this(null, title, null, null);
865+ }
866+
867+ /**
868+ * Constructs a <code>SimpleInternalFrame</code> with the specified icon,
869+ * and title.
870+ *
871+ * @param icon
872+ * the initial icon
873+ * @param title
874+ * the initial title
875+ */
876+ public SimpleInternalFrame(Icon icon, String title)
877+ {
878+ this(icon, title, null, null);
879+ }
880+
881+ /**
882+ * Constructs a <code>SimpleInternalFrame</code> with the specified title,
883+ * tool bar, and content panel.
884+ *
885+ * @param title
886+ * the initial title
887+ * @param bar
888+ * the initial tool bar
889+ * @param content
890+ * the initial content pane
891+ */
892+ public SimpleInternalFrame(String title, JToolBar bar, JComponent content)
893+ {
894+ this(null, title, bar, content);
895+ }
896+
897+ /**
898+ * Constructs a <code>SimpleInternalFrame</code> with the specified icon,
899+ * title, tool bar, and content panel.
900+ *
901+ * @param icon
902+ * the initial icon
903+ * @param title
904+ * the initial title
905+ * @param bar
906+ * the initial tool bar
907+ * @param content
908+ * the initial content pane
909+ */
910+ public SimpleInternalFrame(Icon icon, String title, JToolBar bar,
911+ JComponent content)
912+ {
913+ super(new BorderLayout());
914+ this.isSelected = false;
915+ this.titleLabel = new JLabel(title, icon, SwingConstants.LEADING);
916+ JPanel top = buildHeader(this.titleLabel, bar);
917+
918+ add(top, BorderLayout.NORTH);
919+ if (content != null) {
920+ setContent(content);
921+ }
922+ setBorder(new ShadowBorder());
923+ setSelected(true);
924+ updateHeader();
925+ }
926+
927+ // Public API ***********************************************************
928+
929+ /**
930+ * Returns the frame's icon.
931+ *
932+ * @return the frame's icon
933+ */
934+ public Icon getFrameIcon()
935+ {
936+ return this.titleLabel.getIcon();
937+ }
938+
939+ /**
940+ * Sets a new frame icon.
941+ *
942+ * @param newIcon
943+ * the icon to be set
944+ */
945+ public void setFrameIcon(Icon newIcon)
946+ {
947+ Icon oldIcon = getFrameIcon();
948+ this.titleLabel.setIcon(newIcon);
949+ firePropertyChange("frameIcon", oldIcon, newIcon);
950+ }
951+
952+ /**
953+ * Returns the frame's title text.
954+ *
955+ * @return String the current title text
956+ */
957+ public String getTitle()
958+ {
959+ return this.titleLabel.getText();
960+ }
961+
962+ /**
963+ * Sets a new title text.
964+ *
965+ * @param newText
966+ * the title text tp be set
967+ */
968+ public void setTitle(String newText)
969+ {
970+ String oldText = getTitle();
971+ this.titleLabel.setText(newText);
972+ firePropertyChange("title", oldText, newText);
973+ }
974+
975+ /**
976+ * Returns the current toolbar, null if none has been set before.
977+ *
978+ * @return the current toolbar - if any
979+ */
980+ public JToolBar getToolBar()
981+ {
982+ return this.headerPanel.getComponentCount() > 1 ? (JToolBar) this.headerPanel
983+ .getComponent(1) : null;
984+ }
985+
986+ /**
987+ * Sets a new tool bar in the header.
988+ *
989+ * @param newToolBar
990+ * the tool bar to be set in the header
991+ */
992+ public void setToolBar(JToolBar newToolBar)
993+ {
994+ JToolBar oldToolBar = getToolBar();
995+ if (oldToolBar == newToolBar) {
996+ return;
997+ }
998+ if (oldToolBar != null) {
999+ this.headerPanel.remove(oldToolBar);
1000+ }
1001+ if (newToolBar != null) {
1002+ newToolBar.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
1003+ this.headerPanel.add(newToolBar, BorderLayout.EAST);
1004+ }
1005+ updateHeader();
1006+ firePropertyChange("toolBar", oldToolBar, newToolBar);
1007+ }
1008+
1009+ /**
1010+ * Returns the content - null, if none has been set.
1011+ *
1012+ * @return the current content
1013+ */
1014+ public Component getContent()
1015+ {
1016+ return hasContent() ? getComponent(1) : null;
1017+ }
1018+
1019+ /**
1020+ * Sets a new panel content; replaces any existing content, if existing.
1021+ *
1022+ * @param newContent
1023+ * the panel's new content
1024+ */
1025+ public void setContent(Component newContent)
1026+ {
1027+ Component oldContent = getContent();
1028+ if (hasContent()) {
1029+ remove(oldContent);
1030+ }
1031+ add(newContent, BorderLayout.CENTER);
1032+ firePropertyChange("content", oldContent, newContent);
1033+ }
1034+
1035+ /**
1036+ * Answers if the panel is currently selected (or in other words active) or
1037+ * not. In the selected state, the header background will be rendered
1038+ * differently.
1039+ *
1040+ * @return boolean a boolean, where true means the frame is selected
1041+ * (currently active) and false means it is not
1042+ */
1043+ public boolean isSelected()
1044+ {
1045+ return this.isSelected;
1046+ }
1047+
1048+ /**
1049+ * This panel draws its title bar differently if it is selected, which may
1050+ * be used to indicate to the user that this panel has the focus, or should
1051+ * get more attention than other simple internal frames.
1052+ *
1053+ * @param newValue
1054+ * a boolean, where true means the frame is selected (currently
1055+ * active) and false means it is not
1056+ */
1057+ public void setSelected(boolean newValue)
1058+ {
1059+ boolean oldValue = isSelected();
1060+ this.isSelected = newValue;
1061+ updateHeader();
1062+ firePropertyChange("selected", oldValue, newValue);
1063+ }
1064+
1065+ // Building *************************************************************
1066+
1067+ /**
1068+ * Creates and answers the header panel, that consists of: an icon, a title
1069+ * label, a tool bar, and a gradient background.
1070+ *
1071+ * @param label
1072+ * the label to paint the icon and text
1073+ * @param bar
1074+ * the panel's tool bar
1075+ * @return the panel's built header area
1076+ */
1077+ private JPanel buildHeader(JLabel label, JToolBar bar)
1078+ {
1079+ this.gradientPanel = new GradientPanel(new BorderLayout(),
1080+ getHeaderBackground());
1081+ label.setOpaque(false);
1082+
1083+ this.gradientPanel.add(label, BorderLayout.WEST);
1084+ this.gradientPanel.setBorder(BorderFactory.createEmptyBorder(3, 4, 3, 1));
1085+
1086+ this.headerPanel = new JPanel(new BorderLayout());
1087+ this.headerPanel.add(this.gradientPanel, BorderLayout.CENTER);
1088+ setToolBar(bar);
1089+ this.headerPanel.setBorder(new RaisedHeaderBorder());
1090+ this.headerPanel.setOpaque(false);
1091+ return this.headerPanel;
1092+ }
1093+
1094+ /**
1095+ * Updates the header.
1096+ */
1097+ private void updateHeader()
1098+ {
1099+ this.gradientPanel.setBackground(getHeaderBackground());
1100+ this.gradientPanel.setOpaque(isSelected());
1101+ this.titleLabel.setForeground(getTextForeground(isSelected()));
1102+ this.headerPanel.repaint();
1103+ }
1104+
1105+ /**
1106+ * Updates the UI. In addition to the superclass behavior, we need to update
1107+ * the header component.
1108+ */
1109+ @Override
1110+ public void updateUI()
1111+ {
1112+ super.updateUI();
1113+ if (this.titleLabel != null) {
1114+ updateHeader();
1115+ }
1116+ }
1117+
1118+ // Helper Code **********************************************************
1119+
1120+ /**
1121+ * Checks and answers if the panel has a content component set.
1122+ *
1123+ * @return true if the panel has a content, false if it's empty
1124+ */
1125+ private boolean hasContent()
1126+ {
1127+ return getComponentCount() > 1;
1128+ }
1129+
1130+ /**
1131+ * Determines and answers the header's text foreground color. Tries to
1132+ * lookup a special color from the L&amp;F. In case it is absent, it uses
1133+ * the standard internal frame forground.
1134+ *
1135+ * @param selected
1136+ * true to lookup the active color, false for the inactive
1137+ * @return the color of the foreground text
1138+ */
1139+ protected static Color getTextForeground(boolean selected)
1140+ {
1141+ Color c = UIManager
1142+ .getColor(selected ? "SimpleInternalFrame.activeTitleForeground"
1143+ : "SimpleInternalFrame.inactiveTitleForeground");
1144+ if (c != null) {
1145+ return c;
1146+ }
1147+ return UIManager
1148+ .getColor(selected ? "InternalFrame.activeTitleForeground"
1149+ : "Label.foreground");
1150+
1151+ }
1152+
1153+ /**
1154+ * Determines and answers the header's background color. Tries to lookup a
1155+ * special color from the L&amp;F. In case it is absent, it uses the
1156+ * standard internal frame background.
1157+ *
1158+ * @return the color of the header's background
1159+ */
1160+ protected static Color getHeaderBackground()
1161+ {
1162+ Color c = UIManager
1163+ .getColor("SimpleInternalFrame.activeTitleBackground");
1164+ if (c != null)
1165+ return c;
1166+ if (LookUtils.IS_LAF_WINDOWS_XP_ENABLED)
1167+ c = UIManager.getColor("InternalFrame.activeTitleGradient");
1168+ return c != null ? c : UIManager
1169+ .getColor("InternalFrame.activeTitleBackground");
1170+ }
1171+
1172+ // Helper Classes *******************************************************
1173+
1174+ // A custom border for the raised header pseudo 3D effect.
1175+ private static class RaisedHeaderBorder extends AbstractBorder
1176+ {
1177+
1178+ /**
1179+ *
1180+ */
1181+ private static final long serialVersionUID = -1586862789455436604L;
1182+ private static final Insets INSETS = new Insets(1, 1, 1, 0);
1183+
1184+ @Override
1185+ public Insets getBorderInsets(Component c)
1186+ {
1187+ return INSETS;
1188+ }
1189+
1190+ @Override
1191+ public void paintBorder(Component c, Graphics g, int x, int y, int w,
1192+ int h)
1193+ {
1194+
1195+ g.translate(x, y);
1196+ g.setColor(UIManager.getColor("controlLtHighlight"));
1197+ g.fillRect(0, 0, w, 1);
1198+ g.fillRect(0, 1, 1, h - 1);
1199+ g.setColor(UIManager.getColor("controlShadow"));
1200+ g.fillRect(0, h - 1, w, 1);
1201+ g.translate(-x, -y);
1202+ }
1203+ }
1204+
1205+ // A custom border that has a shadow on the right and lower sides.
1206+ private static class ShadowBorder extends AbstractBorder
1207+ {
1208+
1209+ private static final long serialVersionUID = -4816334256619360379L;
1210+ private static final Insets INSETS = new Insets(1, 1, 3, 3);
1211+
1212+ @Override
1213+ public Insets getBorderInsets(Component c)
1214+ {
1215+ return INSETS;
1216+ }
1217+
1218+ @Override
1219+ public void paintBorder(Component c, Graphics g, int x, int y, int w,
1220+ int h)
1221+ {
1222+
1223+ Color shadow = UIManager.getColor("controlShadow");
1224+ if (shadow == null) {
1225+ shadow = Color.GRAY;
1226+ }
1227+ Color lightShadow = new Color(shadow.getRed(), shadow.getGreen(),
1228+ shadow.getBlue(), 170);
1229+ Color lighterShadow = new Color(shadow.getRed(), shadow.getGreen(),
1230+ shadow.getBlue(), 70);
1231+ g.translate(x, y);
1232+
1233+ g.setColor(shadow);
1234+ g.fillRect(0, 0, w - 3, 1);
1235+ g.fillRect(0, 0, 1, h - 3);
1236+ g.fillRect(w - 3, 1, 1, h - 3);
1237+ g.fillRect(1, h - 3, w - 3, 1);
1238+ // Shadow line 1
1239+ g.setColor(lightShadow);
1240+ g.fillRect(w - 3, 0, 1, 1);
1241+ g.fillRect(0, h - 3, 1, 1);
1242+ g.fillRect(w - 2, 1, 1, h - 3);
1243+ g.fillRect(1, h - 2, w - 3, 1);
1244+ // Shadow line2
1245+ g.setColor(lighterShadow);
1246+ g.fillRect(w - 2, 0, 1, 1);
1247+ g.fillRect(0, h - 2, 1, 1);
1248+ g.fillRect(w - 2, h - 2, 1, 1);
1249+ g.fillRect(w - 1, 1, 1, h - 2);
1250+ g.fillRect(1, h - 1, w - 2, 1);
1251+ g.translate(-x, -y);
1252+ }
1253+ }
1254+
1255+ // A panel with a horizontal gradient background.
1256+ private static class GradientPanel extends JPanel
1257+ {
1258+
1259+ /**
1260+ *
1261+ */
1262+ private static final long serialVersionUID = 6424967938581512289L;
1263+
1264+ private GradientPanel(LayoutManager lm, Color background)
1265+ {
1266+ super(lm);
1267+ setBackground(background);
1268+ }
1269+
1270+ @Override
1271+ public void paintComponent(Graphics g)
1272+ {
1273+ super.paintComponent(g);
1274+ if (!isOpaque()) {
1275+ return;
1276+ }
1277+ Color control = UIManager.getColor("control");
1278+ int width = getWidth();
1279+ int height = getHeight();
1280+
1281+ Graphics2D g2 = (Graphics2D) g;
1282+ Paint storedPaint = g2.getPaint();
1283+ g2.setPaint(new GradientPaint(0, 0, getBackground(), width, 0,
1284+ control));
1285+ g2.fillRect(0, 0, width, height);
1286+ g2.setPaint(storedPaint);
1287+ }
1288+ }
1289+
1290+}
1291\ No newline at end of file
1292
1293=== added directory 'src/com/microstar'
1294=== added directory 'src/com/microstar/xml'
1295=== added file 'src/com/microstar/xml/HandlerBase.java'
1296--- src/com/microstar/xml/HandlerBase.java 1970-01-01 00:00:00 +0000
1297+++ src/com/microstar/xml/HandlerBase.java 2011-12-27 11:11:23 +0000
1298@@ -0,0 +1,193 @@
1299+// HandlerBase.java: Simple base class for AElfred processors.
1300+// NO WARRANTY! See README, and copyright below.
1301+// $Id: HandlerBase.java,v 1.1 2008-03-02 00:22:50 lywoon Exp $
1302+
1303+package com.microstar.xml;
1304+
1305+/**
1306+ * Convenience base class for AElfred handlers.
1307+ * <p>
1308+ * This base class implements the XmlHandler interface with (mostly empty)
1309+ * default handlers. You are not required to use this, but if you need to handle
1310+ * only a few events, you might find it convenient to extend this class rather
1311+ * than implementing the entire interface. This example overrides only the
1312+ * <code>charData</code> method, using the defaults for the others:
1313+ *
1314+ * <pre>
1315+ *
1316+ * import com.microstar.xml.HandlerBase;
1317+ *
1318+ * public class MyHandler extends HandlerBase {
1319+ * public void charData(char ch[], int start, int length) {
1320+ * System.out.println(&quot;Data: &quot; + new String(ch, start, length));
1321+ * }
1322+ * }
1323+ * </pre>
1324+ *
1325+ * <p>
1326+ * This class is optional, but if you use it, you must also include the
1327+ * <code>XmlException</code> class.
1328+ * <p>
1329+ * Do not extend this if you are using SAX; extend
1330+ * <code>org.xml.sax.HandlerBase</code> instead.
1331+ *
1332+ * @author Copyright (c) 1998 by Microstar Software Ltd.
1333+ * @author written by David Megginson &lt;dmeggins@microstar.com&gt;
1334+ * @version 1.1
1335+ * @see XmlHandler
1336+ * @see XmlException
1337+ * @see org.xml.sax.HandlerBase
1338+ */
1339+public abstract class HandlerBase implements XmlHandler {
1340+
1341+ /**
1342+ * Handle the start of the document.
1343+ * <p>
1344+ * The default implementation does nothing.
1345+ *
1346+ * @see com.microstar.xml.XmlHandler#startDocument
1347+ */
1348+ @Override
1349+ public void startDocument() {
1350+ }
1351+
1352+ /**
1353+ * Handle the end of the document.
1354+ * <p>
1355+ * The default implementation does nothing.
1356+ *
1357+ * @see com.microstar.xml.XmlHandler#endDocument
1358+ */
1359+ @Override
1360+ public void endDocument() {
1361+ }
1362+
1363+ /**
1364+ * Resolve an external entity.
1365+ * <p>
1366+ * The default implementation simply returns the supplied system identifier.
1367+ *
1368+ * @see com.microstar.xml.XmlHandler#resolveEntity
1369+ */
1370+ @Override
1371+ public Object resolveEntity(String publicId, String systemId) {
1372+ return null;
1373+ }
1374+
1375+ /**
1376+ * Handle the start of an external entity.
1377+ * <p>
1378+ * The default implementation does nothing.
1379+ *
1380+ * @see com.microstar.xml.XmlHandler#startExternalEntity
1381+ */
1382+ @Override
1383+ public void startExternalEntity(String systemId) {
1384+ }
1385+
1386+ /**
1387+ * Handle the end of an external entity.
1388+ * <p>
1389+ * The default implementation does nothing.
1390+ *
1391+ * @see com.microstar.xml.XmlHandler#endExternalEntity
1392+ */
1393+ @Override
1394+ public void endExternalEntity(String systemId) {
1395+ }
1396+
1397+ /**
1398+ * Handle a document type declaration.
1399+ * <p>
1400+ * The default implementation does nothing.
1401+ *
1402+ * @see com.microstar.xml.XmlHandler#doctypeDecl
1403+ */
1404+ @Override
1405+ public void doctypeDecl(String name, String publicId, String systemId) {
1406+ }
1407+
1408+ /**
1409+ * Handle an attribute assignment.
1410+ * <p>
1411+ * The default implementation does nothing.
1412+ *
1413+ * @see com.microstar.xml.XmlHandler#attribute
1414+ */
1415+ @Override
1416+ public void attribute(String aname, String value, boolean isSpecified) {
1417+ }
1418+
1419+ /**
1420+ * Handle the start of an element.
1421+ * <p>
1422+ * The default implementation does nothing.
1423+ *
1424+ * @see com.microstar.xml.XmlHandler#startElement
1425+ */
1426+ @Override
1427+ public void startElement(String elname) {
1428+ }
1429+
1430+ /**
1431+ * Handle the end of an element.
1432+ * <p>
1433+ * The default implementation does nothing.
1434+ *
1435+ * @see com.microstar.xml.XmlHandler#endElement
1436+ */
1437+ @Override
1438+ public void endElement(String elname) {
1439+ }
1440+
1441+ /**
1442+ * Handle character data.
1443+ * <p>
1444+ * The default implementation does nothing.
1445+ *
1446+ * @see com.microstar.xml.XmlHandler#charData
1447+ */
1448+ @Override
1449+ public void charData(char ch[], int start, int length) {
1450+ }
1451+
1452+ /**
1453+ * Handle ignorable whitespace.
1454+ * <p>
1455+ * The default implementation does nothing.
1456+ *
1457+ * @see com.microstar.xml.XmlHandler#ignorableWhitespace
1458+ */
1459+ @Override
1460+ public void ignorableWhitespace(char ch[], int start, int length) {
1461+ }
1462+
1463+ /**
1464+ * Handle a processing instruction.
1465+ * <p>
1466+ * The default implementation does nothing.
1467+ *
1468+ * @see com.microstar.xml.XmlHandler#processingInstruction
1469+ */
1470+ @Override
1471+ public void processingInstruction(String target, String data) {
1472+ }
1473+
1474+ /**
1475+ * Throw an exception for a fatal error.
1476+ * <p>
1477+ * The default implementation throws <code>XmlException</code>.
1478+ *
1479+ * @see com.microstar.xml.XmlHandler#error
1480+ * @exception com.microstar.xml.XmlException
1481+ * A specific parsing error.
1482+ * @exception java.lang.Exception
1483+ * Derived methods may throw exceptions.
1484+ */
1485+ @Override
1486+ public void error(String message, String systemId, int line, int column)
1487+ throws XmlException, java.lang.Exception {
1488+ throw new XmlException(message, systemId, line, column);
1489+ }
1490+
1491+}
1492\ No newline at end of file
1493
1494=== added file 'src/com/microstar/xml/XmlException.java'
1495--- src/com/microstar/xml/XmlException.java 1970-01-01 00:00:00 +0000
1496+++ src/com/microstar/xml/XmlException.java 2011-12-27 11:11:23 +0000
1497@@ -0,0 +1,99 @@
1498+// XmlException.java: Simple base class for AElfred processors.
1499+// NO WARRANTY! See README, and copyright below.
1500+// $Id: XmlException.java,v 1.1 2008-03-02 00:22:50 lywoon Exp $
1501+
1502+package com.microstar.xml;
1503+
1504+/**
1505+ * Convenience exception class for reporting XML parsing errors.
1506+ * <p>
1507+ * This is an exception class that you can use to encapsulate all of the
1508+ * information from &AElig;lfred's <code>error</code> callback. This is not
1509+ * necessary for routine use of &AElig;lfred, but it is used by the optional
1510+ * <code>HandlerBase</code> class.
1511+ * <p>
1512+ * Note that the core &AElig;lfred classes do <em>not</em> use this exception.
1513+ *
1514+ * @author Copyright (c) 1998 by Microstar Software Ltd.
1515+ * @author written by David Megginson &lt;dmeggins@microstar.com&gt;
1516+ * @version 1.1
1517+ * @see XmlHandler#error
1518+ * @see HandlerBase
1519+ */
1520+public class XmlException extends Exception
1521+{
1522+ /**
1523+ *
1524+ */
1525+ private static final long serialVersionUID = 296196241316747669L;
1526+
1527+ private String message;
1528+
1529+ private String systemId;
1530+
1531+ private int line;
1532+
1533+ private int column;
1534+
1535+ /**
1536+ * Construct a new XML parsing exception.
1537+ *
1538+ * @param message
1539+ * The error message from the parser.
1540+ * @param systemId
1541+ * The URI of the entity containing the error.
1542+ * @param line
1543+ * The line number where the error appeared.
1544+ * @param column
1545+ * The column number where the error appeared.
1546+ */
1547+ public XmlException(String message, String systemId, int line, int column)
1548+ {
1549+ this.message = message;
1550+ this.systemId = systemId;
1551+ this.line = line;
1552+ this.column = column;
1553+ }
1554+
1555+ /**
1556+ * Get the error message from the parser.
1557+ *
1558+ * @return A string describing the error.
1559+ */
1560+ @Override
1561+ public String getMessage()
1562+ {
1563+ return this.message;
1564+ }
1565+
1566+ /**
1567+ * Get the URI of the entity containing the error.
1568+ *
1569+ * @return The URI as a string.
1570+ */
1571+ public String getSystemId()
1572+ {
1573+ return this.systemId;
1574+ }
1575+
1576+ /**
1577+ * Get the line number containing the error.
1578+ *
1579+ * @return The line number as an integer.
1580+ */
1581+ public int getLine()
1582+ {
1583+ return this.line;
1584+ }
1585+
1586+ /**
1587+ * Get the column number containing the error.
1588+ *
1589+ * @return The column number as an integer.
1590+ */
1591+ public int getColumn()
1592+ {
1593+ return this.column;
1594+ }
1595+
1596+}
1597\ No newline at end of file
1598
1599=== added file 'src/com/microstar/xml/XmlHandler.java'
1600--- src/com/microstar/xml/XmlHandler.java 1970-01-01 00:00:00 +0000
1601+++ src/com/microstar/xml/XmlHandler.java 2011-12-27 11:11:23 +0000
1602@@ -0,0 +1,291 @@
1603+// XmlHandler.java: the callback interface.
1604+// NO WARRANTY! See README, and copyright below.
1605+// $Id: XmlHandler.java,v 1.1 2008-03-02 00:22:50 lywoon Exp $
1606+
1607+package com.microstar.xml;
1608+
1609+/**
1610+ * XML Processing Interface.
1611+ * <p>
1612+ * Whenever you parse an XML document, you must provide an object from a class
1613+ * that implements this interface to receive the parsing events.
1614+ * <p>
1615+ * If you do not want to implement this entire interface, you can extend the
1616+ * <code>HandlerBase</code> convenience class and then implement only what you
1617+ * need.
1618+ * <p>
1619+ * If you are using SAX, you should implement the SAX handler interfaces rather
1620+ * than this one.
1621+ *
1622+ * @author Copyright (c) 1997, 1998 by Microstar Software Ltd.
1623+ * @author written by David Megginson &lt;dmeggins@microstar.com&gt;
1624+ * @version 1.1
1625+ * @see XmlParser
1626+ * @see HandlerBase
1627+ * @see org.xml.sax.EntityHandler
1628+ * @see org.xml.sax.DocumentHandler
1629+ * @see org.xml.sax.ErrorHandler
1630+ */
1631+public interface XmlHandler
1632+{
1633+
1634+ /**
1635+ * Start the document.
1636+ * <p>
1637+ * &AElig;lfred will call this method just before it attempts to read the
1638+ * first entity (the root of the document). It is guaranteed that this will
1639+ * be the first method called.
1640+ *
1641+ * @exception java.lang.Exception
1642+ * The handler may throw any exception.
1643+ * @see #endDocument
1644+ */
1645+ public void startDocument() throws java.lang.Exception;
1646+
1647+ /**
1648+ * End the document.
1649+ * <p>
1650+ * &AElig;lfred will call this method once, when it has finished parsing the
1651+ * XML document. It is guaranteed that this will be the last method called.
1652+ *
1653+ * @exception java.lang.Exception
1654+ * The handler may throw any exception.
1655+ * @see #startDocument
1656+ */
1657+ public void endDocument() throws java.lang.Exception;
1658+
1659+ /**
1660+ * Resolve an External Entity.
1661+ * <p>
1662+ * Give the handler a chance to redirect external entities to different
1663+ * URIs. &AElig;lfred will call this method for the top-level document
1664+ * entity, for external text (XML) entities, and the external DTD subset (if
1665+ * any).
1666+ *
1667+ * @param publicId
1668+ * The public identifier, or null if none was supplied.
1669+ * @param systemId
1670+ * The system identifier.
1671+ * @return The replacement system identifier, or null to use the default.
1672+ * @exception java.lang.Exception
1673+ * The handler may throw any exception.
1674+ * @see #startExternalEntity
1675+ * @see #endExternalEntity
1676+ */
1677+ public Object resolveEntity(String publicId, String systemId)
1678+ throws java.lang.Exception;
1679+
1680+ /**
1681+ * Begin an external entity.
1682+ * <p>
1683+ * &AElig;lfred will call this method at the beginning of each external
1684+ * entity, including the top-level document entity and the external DTD
1685+ * subset (if any).
1686+ * <p>
1687+ * If necessary, you can use this method to track the location of the
1688+ * current entity so that you can resolve relative URIs correctly.
1689+ *
1690+ * @param systemId
1691+ * The URI of the external entity that is starting.
1692+ * @exception java.lang.Exception
1693+ * The handler may throw any exception.
1694+ * @see #endExternalEntity
1695+ * @see #resolveEntity
1696+ */
1697+ public void startExternalEntity(String systemId) throws java.lang.Exception;
1698+
1699+ /**
1700+ * End an external entity.
1701+ * <p>
1702+ * &AElig;lfred will call this method at the end of each external entity,
1703+ * including the top-level document entity and the external DTD subset.
1704+ * <p>
1705+ * If necessary, you can use this method to track the location of the
1706+ * current entity so that you can resolve relative URIs correctly.
1707+ *
1708+ * @param systemId
1709+ * The URI of the external entity that is ending.
1710+ * @exception java.lang.Exception
1711+ * The handler may throw any exception.
1712+ * @see #startExternalEntity
1713+ * @see #resolveEntity
1714+ */
1715+ public void endExternalEntity(String systemId) throws java.lang.Exception;
1716+
1717+ /**
1718+ * Document type declaration.
1719+ * <p>
1720+ * &AElig;lfred will call this method when or if it encounters the document
1721+ * type (DOCTYPE) declaration.
1722+ * <p>
1723+ * Please note that the public and system identifiers will not always be a
1724+ * reliable indication of the DTD in use.
1725+ *
1726+ * @param name
1727+ * The document type name.
1728+ * @param publicId
1729+ * The public identifier, or null if unspecified.
1730+ * @param systemId
1731+ * The system identifier, or null if unspecified.
1732+ * @exception java.lang.Exception
1733+ * The handler may throw any exception.
1734+ */
1735+ public void doctypeDecl(String name, String publicId, String systemId)
1736+ throws java.lang.Exception;
1737+
1738+ /**
1739+ * Attribute.
1740+ * <p>
1741+ * &AElig;lfred will call this method once for each attribute (specified or
1742+ * defaulted) before reporting a startElement event. It is up to your
1743+ * handler to collect the attributes, if necessary.
1744+ * <p>
1745+ * You may use XmlParser.getAttributeType() to find the attribute's declared
1746+ * type.
1747+ *
1748+ * @param name
1749+ * The name of the attribute.
1750+ * @param type
1751+ * The type of the attribute (see below).
1752+ * @param value
1753+ * The value of the attribute, or null if the attribute is
1754+ * <code>#IMPLIED</code>.
1755+ * @param isSpecified
1756+ * True if the value was specified, false if it was defaulted
1757+ * from the DTD.
1758+ * @exception java.lang.Exception
1759+ * The handler may throw any exception.
1760+ * @see #startElement
1761+ * @see XmlParser#declaredAttributes
1762+ * @see XmlParser#getAttributeType
1763+ * @see XmlParser#getAttributeDefaultValue
1764+ */
1765+ public void attribute(String aname, String value, boolean isSpecified)
1766+ throws java.lang.Exception;
1767+
1768+ /**
1769+ * Start an element.
1770+ * <p>
1771+ * &AElig;lfred will call this method at the beginning of each element. By
1772+ * the time this is called, all of the attributes for the element will
1773+ * already have been reported using the <code>attribute</code> method.
1774+ *
1775+ * @param elname
1776+ * The element type name.
1777+ * @exception java.lang.Exception
1778+ * The handler may throw any exception.
1779+ * @see #attribute
1780+ * @see #endElement
1781+ * @see XmlParser#declaredElements
1782+ * @see XmlParser#getElementContentType
1783+ */
1784+ public void startElement(String elname) throws java.lang.Exception;
1785+
1786+ /**
1787+ * End an element.
1788+ * <p>
1789+ * &AElig;lfred will call this method at the end of each element (including
1790+ * EMPTY elements).
1791+ *
1792+ * @param elname
1793+ * The element type name.
1794+ * @exception java.lang.Exception
1795+ * The handler may throw any exception.
1796+ * @see #startElement
1797+ * @see XmlParser#declaredElements
1798+ * @see XmlParser#getElementContentType
1799+ */
1800+ public void endElement(String elname) throws java.lang.Exception;
1801+
1802+ /**
1803+ * Character data.
1804+ * <p>
1805+ * &AElig;lfred will call this method once for each chunk of character data
1806+ * found in the contents of elements. Note that the parser may break up a
1807+ * long sequence of characters into smaller chunks and call this method once
1808+ * for each chunk.
1809+ * <p>
1810+ * Do <em>not</em> attempt to read more than <var>length </var> characters
1811+ * from the array, or to read before the <var>start </var> position.
1812+ *
1813+ * @param ch
1814+ * The character data.
1815+ * @param start
1816+ * The starting position in the array.
1817+ * @param length
1818+ * The number of characters available.
1819+ * @exception java.lang.Exception
1820+ * The handler may throw any exception.
1821+ */
1822+ public void charData(char ch[], int start, int length)
1823+ throws java.lang.Exception;
1824+
1825+ /**
1826+ * Ignorable whitespace.
1827+ * <p>
1828+ * &AElig;lfred will call this method once for each sequence of ignorable
1829+ * whitespace in element content (never in mixed content).
1830+ * <p>
1831+ * For details, see section 2.10 of the XML 1.0 recommendation.
1832+ * <p>
1833+ * Do <em>not</em> attempt to read more than <var>length </var> characters
1834+ * from the array or to read before the <var>start </var> position.
1835+ *
1836+ * @param ch
1837+ * The literal whitespace characters.
1838+ * @param start
1839+ * The starting position in the array.
1840+ * @param length
1841+ * The number of whitespace characters available.
1842+ * @exception java.lang.Exception
1843+ * The handler may throw any exception.
1844+ */
1845+ public void ignorableWhitespace(char ch[], int start, int length)
1846+ throws java.lang.Exception;
1847+
1848+ /**
1849+ * Processing instruction.
1850+ * <p>
1851+ * &AElig;lfred will call this method once for each processing instruction.
1852+ * Note that processing instructions may appear outside of the top-level
1853+ * element. The
1854+ *
1855+ * @param target
1856+ * The target (the name at the start of the PI).
1857+ * @param data
1858+ * The data, if any (the rest of the PI).
1859+ * @exception java.lang.Exception
1860+ * The handler may throw any exception.
1861+ */
1862+ public void processingInstruction(String target, String data)
1863+ throws java.lang.Exception;
1864+
1865+ /**
1866+ * Fatal XML parsing error.
1867+ * <p>
1868+ * &AElig;lfred will call this method whenever it encounters a serious
1869+ * error. The parser will attempt to continue past this point so that you
1870+ * can find more possible error points, but if this method is called you
1871+ * should assume that the document is corrupt and you should not try to use
1872+ * its contents.
1873+ * <p>
1874+ * Note that you can use the <code>XmlException</code> class to
1875+ * encapsulate all of the information provided, though the use of the class
1876+ * is not mandatory.
1877+ *
1878+ * @param message
1879+ * The error message.
1880+ * @param systemId
1881+ * The system identifier of the entity that contains the error.
1882+ * @param line
1883+ * The approximate line number of the error.
1884+ * @param column
1885+ * The approximate column number of the error.
1886+ * @exception java.lang.Exception
1887+ * The handler may throw any exception.
1888+ * @see XmlException
1889+ */
1890+ public void error(String message, String systemId, int line, int column)
1891+ throws java.lang.Exception;
1892+
1893+}
1894\ No newline at end of file
1895
1896=== added file 'src/com/microstar/xml/XmlParser.java'
1897--- src/com/microstar/xml/XmlParser.java 1970-01-01 00:00:00 +0000
1898+++ src/com/microstar/xml/XmlParser.java 2011-12-27 11:11:23 +0000
1899@@ -0,0 +1,4312 @@
1900+// XmlParser.java: the main parser class.
1901+// NO WARRANTY! See README, and copyright below.
1902+// $Id: XmlParser.java,v 1.3 2009-12-16 21:59:29 bruno Exp $
1903+
1904+package com.microstar.xml;
1905+
1906+import java.io.BufferedInputStream;
1907+import java.io.EOFException;
1908+import java.io.InputStream;
1909+import java.io.Reader;
1910+import java.net.URL;
1911+import java.net.URLConnection;
1912+import java.util.Enumeration;
1913+import java.util.Hashtable;
1914+import java.util.Stack;
1915+
1916+/**
1917+ * Parse XML documents and return parse events through call-backs.
1918+ * <p>
1919+ * You need to define a class implementing the <code>XmlHandler</code>
1920+ * interface: an object belonging to this class will receive the callbacks for
1921+ * the events. (As an alternative to implementing the full XmlHandler interface,
1922+ * you can simply extend the <code>HandlerBase</code> convenience class.)
1923+ * <p>
1924+ * Usage (assuming that <code>MyHandler</code> is your implementation of the
1925+ * <code>XmlHandler</code> interface):
1926+ *
1927+ * <pre>
1928+ *
1929+ *
1930+ *
1931+ * XmlHandler handler = new MyHandler();
1932+ * XmlParser parser = new XmlParser();
1933+ * parser.setHandler(handler);
1934+ * try {
1935+ * parser.parse(&quot;http://www.host.com/doc.xml&quot;, null);
1936+ * } catch (Exception e) {
1937+ * [do something interesting]
1938+ * }
1939+ *
1940+ *
1941+ *
1942+ * </pre>
1943+ *
1944+ * <p>
1945+ * Alternatively, you can use the standard SAX interfaces with the
1946+ * <code>SAXDriver</code> class as your entry point.
1947+ *
1948+ * @author Copyright (c) 1997, 1998 by Microstar Software Ltd.
1949+ * @author Written by David Megginson &lt;dmeggins@microstar.com&gt;
1950+ * @version 1.1
1951+ * @see XmlHandler
1952+ * @see HandlerBase
1953+ * @see SAXDriver
1954+ */
1955+public class XmlParser
1956+{
1957+
1958+ //
1959+ // Use special cheats that speed up the code (currently about 50%),
1960+ // but may cause problems with future maintenance and add to the
1961+ // class file size (about 500 bytes).
1962+ //
1963+ private final static boolean USE_CHEATS = true;
1964+
1965+ //////////////////////////////////////////////////////////////////////
1966+ // Constructors.
1967+ ////////////////////////////////////////////////////////////////////////
1968+
1969+ /**
1970+ * Construct a new parser with no associated handler.
1971+ *
1972+ * @see #setHandler
1973+ * @see #parse
1974+ */
1975+ public XmlParser()
1976+ {
1977+ }
1978+
1979+ /**
1980+ * Set the handler that will receive parsing events.
1981+ *
1982+ * @param handler
1983+ * The handler to receive callback events.
1984+ * @see #parse
1985+ * @see XmlHandler
1986+ */
1987+ public void setHandler(XmlHandler handler)
1988+ {
1989+ this.handler = handler;
1990+ }
1991+
1992+ /**
1993+ * Parse an XML document from a URI.
1994+ * <p>
1995+ * You may parse a document more than once, but only one thread may call
1996+ * this method for an object at one time.
1997+ *
1998+ * @param systemId
1999+ * The URI of the document.
2000+ * @param publicId
2001+ * The public identifier of the document, or null.
2002+ * @param encoding
2003+ * The suggested encoding, or null if unknown.
2004+ * @exception java.lang.Exception
2005+ * Any exception thrown by your own handlers, or any
2006+ * derivation of java.io.IOException thrown by the parser
2007+ * itself.
2008+ */
2009+ public void parse(String systemId, String publicId, String encoding)
2010+ throws java.lang.Exception
2011+ {
2012+ doParse(systemId, publicId, null, null, encoding);
2013+ }
2014+
2015+ /**
2016+ * Parse an XML document from a byte stream.
2017+ * <p>
2018+ * The URI that you supply will become the base URI for resolving relative
2019+ * links, but &AElig;lfred will actually read the document from the supplied
2020+ * input stream.
2021+ * <p>
2022+ * You may parse a document more than once, but only one thread may call
2023+ * this method for an object at one time.
2024+ *
2025+ * @param systemId
2026+ * The base URI of the document, or null if not known.
2027+ * @param publicId
2028+ * The public identifier of the document, or null if not known.
2029+ * @param stream
2030+ * A byte input stream.
2031+ * @param encoding
2032+ * The suggested encoding, or null if unknown.
2033+ * @exception java.lang.Exception
2034+ * Any exception thrown by your own handlers, or any
2035+ * derivation of java.io.IOException thrown by the parser
2036+ * itself.
2037+ */
2038+ public void parse(String systemId, String publicId, InputStream stream,
2039+ String encoding) throws java.lang.Exception
2040+ {
2041+ doParse(systemId, publicId, null, stream, encoding);
2042+ }
2043+
2044+ /**
2045+ * Parse an XML document from a character stream.
2046+ * <p>
2047+ * The URI that you supply will become the base URI for resolving relative
2048+ * links, but &AElig;lfred will actually read the document from the supplied
2049+ * input stream.
2050+ * <p>
2051+ * You may parse a document more than once, but only one thread may call
2052+ * this method for an object at one time.
2053+ *
2054+ * @param systemId
2055+ * The base URI of the document, or null if not known.
2056+ * @param publicId
2057+ * The public identifier of the document, or null if not known.
2058+ * @param reader
2059+ * A character stream.
2060+ * @exception java.lang.Exception
2061+ * Any exception thrown by your own handlers, or any
2062+ * derivation of java.io.IOException thrown by the parser
2063+ * itself.
2064+ */
2065+ public void parse(String systemId, String publicId, Reader reader)
2066+ throws java.lang.Exception
2067+ {
2068+ doParse(systemId, publicId, reader, null, null);
2069+ }
2070+
2071+ private synchronized void doParse(String systemId, String publicId,
2072+ Reader reader, InputStream stream, String encoding)
2073+ throws java.lang.Exception
2074+ {
2075+ this.basePublicId = publicId;
2076+ this.baseURI = systemId;
2077+ this.baseReader = reader;
2078+ this.baseInputStream = stream;
2079+
2080+ initializeVariables();
2081+
2082+ // Set the default entities here.
2083+ setInternalEntity(intern("amp"), "&#38;");
2084+ setInternalEntity(intern("lt"), "&#60;");
2085+ setInternalEntity(intern("gt"), "&#62;");
2086+ setInternalEntity(intern("apos"), "&#39;");
2087+ setInternalEntity(intern("quot"), "&#34;");
2088+
2089+ if (this.handler != null) {
2090+ this.handler.startDocument();
2091+ }
2092+
2093+ pushURL("[document]", this.basePublicId, this.baseURI, this.baseReader,
2094+ this.baseInputStream, encoding);
2095+
2096+ parseDocument();
2097+
2098+ if (this.handler != null) {
2099+ this.handler.endDocument();
2100+ }
2101+ cleanupVariables();
2102+ }
2103+
2104+ ////////////////////////////////////////////////////////////////////////
2105+ // Constants.
2106+ ////////////////////////////////////////////////////////////////////////
2107+
2108+ //
2109+ // Constants for element content type.
2110+ //
2111+
2112+ /**
2113+ * Constant: an element has not been declared.
2114+ *
2115+ * @see #getElementContentType
2116+ */
2117+ public final static int CONTENT_UNDECLARED = 0;
2118+
2119+ /**
2120+ * Constant: the element has a content model of ANY.
2121+ *
2122+ * @see #getElementContentType
2123+ */
2124+ public final static int CONTENT_ANY = 1;
2125+
2126+ /**
2127+ * Constant: the element has declared content of EMPTY.
2128+ *
2129+ * @see #getElementContentType
2130+ */
2131+ public final static int CONTENT_EMPTY = 2;
2132+
2133+ /**
2134+ * Constant: the element has mixed content.
2135+ *
2136+ * @see #getElementContentType
2137+ */
2138+ public final static int CONTENT_MIXED = 3;
2139+
2140+ /**
2141+ * Constant: the element has element content.
2142+ *
2143+ * @see #getElementContentType
2144+ */
2145+ public final static int CONTENT_ELEMENTS = 4;
2146+
2147+ //
2148+ // Constants for the entity type.
2149+ //
2150+
2151+ /**
2152+ * Constant: the entity has not been declared.
2153+ *
2154+ * @see #getEntityType
2155+ */
2156+ public final static int ENTITY_UNDECLARED = 0;
2157+
2158+ /**
2159+ * Constant: the entity is internal.
2160+ *
2161+ * @see #getEntityType
2162+ */
2163+ public final static int ENTITY_INTERNAL = 1;
2164+
2165+ /**
2166+ * Constant: the entity is external, non-XML data.
2167+ *
2168+ * @see #getEntityType
2169+ */
2170+ public final static int ENTITY_NDATA = 2;
2171+
2172+ /**
2173+ * Constant: the entity is external XML data.
2174+ *
2175+ * @see #getEntityType
2176+ */
2177+ public final static int ENTITY_TEXT = 3;
2178+
2179+ //
2180+ // Constants for attribute type.
2181+ //
2182+
2183+ /**
2184+ * Constant: the attribute has not been declared for this element type.
2185+ *
2186+ * @see #getAttributeType
2187+ */
2188+ public final static int ATTRIBUTE_UNDECLARED = 0;
2189+
2190+ /**
2191+ * Constant: the attribute value is a string value.
2192+ *
2193+ * @see #getAttributeType
2194+ */
2195+ public final static int ATTRIBUTE_CDATA = 1;
2196+
2197+ /**
2198+ * Constant: the attribute value is a unique identifier.
2199+ *
2200+ * @see #getAttributeType
2201+ */
2202+ public final static int ATTRIBUTE_ID = 2;
2203+
2204+ /**
2205+ * Constant: the attribute value is a reference to a unique identifier.
2206+ *
2207+ * @see #getAttributeType
2208+ */
2209+ public final static int ATTRIBUTE_IDREF = 3;
2210+
2211+ /**
2212+ * Constant: the attribute value is a list of ID references.
2213+ *
2214+ * @see #getAttributeType
2215+ */
2216+ public final static int ATTRIBUTE_IDREFS = 4;
2217+
2218+ /**
2219+ * Constant: the attribute value is the name of an entity.
2220+ *
2221+ * @see #getAttributeType
2222+ */
2223+ public final static int ATTRIBUTE_ENTITY = 5;
2224+
2225+ /**
2226+ * Constant: the attribute value is a list of entity names.
2227+ *
2228+ * @see #getAttributeType
2229+ */
2230+ public final static int ATTRIBUTE_ENTITIES = 6;
2231+
2232+ /**
2233+ * Constant: the attribute value is a name token.
2234+ *
2235+ * @see #getAttributeType
2236+ */
2237+ public final static int ATTRIBUTE_NMTOKEN = 7;
2238+
2239+ /**
2240+ * Constant: the attribute value is a list of name tokens.
2241+ *
2242+ * @see #getAttributeType
2243+ */
2244+ public final static int ATTRIBUTE_NMTOKENS = 8;
2245+
2246+ /**
2247+ * Constant: the attribute value is a token from an enumeration.
2248+ *
2249+ * @see #getAttributeType
2250+ */
2251+ public final static int ATTRIBUTE_ENUMERATED = 9;
2252+
2253+ /**
2254+ * Constant: the attribute is the name of a notation.
2255+ *
2256+ * @see #getAttributeType
2257+ */
2258+ public final static int ATTRIBUTE_NOTATION = 10;
2259+
2260+ //
2261+ // When the class is loaded, populate the hash table of
2262+ // attribute types.
2263+ //
2264+
2265+ /**
2266+ * Hash table of attribute types.
2267+ */
2268+ private static Hashtable<String, Integer> attributeTypeHash;
2269+ static {
2270+ attributeTypeHash = new Hashtable<String, Integer>();
2271+ attributeTypeHash.put("CDATA", new Integer(ATTRIBUTE_CDATA));
2272+ attributeTypeHash.put("ID", new Integer(ATTRIBUTE_ID));
2273+ attributeTypeHash.put("IDREF", new Integer(ATTRIBUTE_IDREF));
2274+ attributeTypeHash.put("IDREFS", new Integer(ATTRIBUTE_IDREFS));
2275+ attributeTypeHash.put("ENTITY", new Integer(ATTRIBUTE_ENTITY));
2276+ attributeTypeHash.put("ENTITIES", new Integer(ATTRIBUTE_ENTITIES));
2277+ attributeTypeHash.put("NMTOKEN", new Integer(ATTRIBUTE_NMTOKEN));
2278+ attributeTypeHash.put("NMTOKENS", new Integer(ATTRIBUTE_NMTOKENS));
2279+ attributeTypeHash.put("NOTATION", new Integer(ATTRIBUTE_NOTATION));
2280+ }
2281+
2282+ //
2283+ // Constants for supported encodings.
2284+ //
2285+ private final static int ENCODING_UTF_8 = 1;
2286+
2287+ private final static int ENCODING_ISO_8859_1 = 2;
2288+
2289+ private final static int ENCODING_UCS_2_12 = 3;
2290+
2291+ private final static int ENCODING_UCS_2_21 = 4;
2292+
2293+ private final static int ENCODING_UCS_4_1234 = 5;
2294+
2295+ private final static int ENCODING_UCS_4_4321 = 6;
2296+
2297+ private final static int ENCODING_UCS_4_2143 = 7;
2298+
2299+ private final static int ENCODING_UCS_4_3412 = 8;
2300+
2301+
2302+
2303+ //
2304+ // Constants for attribute default value.
2305+ //
2306+
2307+ /**
2308+ * Constant: the attribute is not declared.
2309+ *
2310+ * @see #getAttributeDefaultValueType
2311+ */
2312+ public final static int ATTRIBUTE_DEFAULT_UNDECLARED = 0;
2313+
2314+ /**
2315+ * Constant: the attribute has a literal default value specified.
2316+ *
2317+ * @see #getAttributeDefaultValueType
2318+ * @see #getAttributeDefaultValue
2319+ */
2320+ public final static int ATTRIBUTE_DEFAULT_SPECIFIED = 1;
2321+
2322+ /**
2323+ * Constant: the attribute was declared #IMPLIED.
2324+ *
2325+ * @see #getAttributeDefaultValueType
2326+ */
2327+ public final static int ATTRIBUTE_DEFAULT_IMPLIED = 2;
2328+
2329+ /**
2330+ * Constant: the attribute was declared #REQUIRED.
2331+ *
2332+ * @see #getAttributeDefaultValueType
2333+ */
2334+ public final static int ATTRIBUTE_DEFAULT_REQUIRED = 3;
2335+
2336+ /**
2337+ * Constant: the attribute was declared #FIXED.
2338+ *
2339+ * @see #getAttributeDefaultValueType
2340+ * @see #getAttributeDefaultValue
2341+ */
2342+ public final static int ATTRIBUTE_DEFAULT_FIXED = 4;
2343+
2344+ //
2345+ // Constants for input.
2346+ //
2347+ private final static int INPUT_NONE = 0;
2348+
2349+ private final static int INPUT_INTERNAL = 1;
2350+
2351+ private final static int INPUT_EXTERNAL = 2;
2352+
2353+ private final static int INPUT_STREAM = 3;
2354+
2355+ private final static int INPUT_BUFFER = 4;
2356+
2357+ private final static int INPUT_READER = 5;
2358+
2359+ //
2360+ // Flags for reading literals.
2361+ //
2362+ private final static int LIT_CHAR_REF = 1;
2363+
2364+ private final static int LIT_ENTITY_REF = 2;
2365+
2366+ private final static int LIT_PE_REF = 4;
2367+
2368+ private final static int LIT_NORMALIZE = 8;
2369+
2370+ //
2371+ // Flags for parsing context.
2372+ //
2373+ private final static int CONTEXT_NONE = 0;
2374+
2375+ private final static int CONTEXT_DTD = 1;
2376+
2377+ private final static int CONTEXT_ENTITYVALUE = 2;
2378+
2379+ private final static int CONTEXT_ATTRIBUTEVALUE = 3;
2380+
2381+ //////////////////////////////////////////////////////////////////////
2382+ // Error reporting.
2383+ //////////////////////////////////////////////////////////////////////
2384+
2385+ /**
2386+ * Report an error.
2387+ *
2388+ * @param message
2389+ * The error message.
2390+ * @param textFound
2391+ * The text that caused the error (or null).
2392+ * @see XmlHandler#error
2393+ * @see #line
2394+ */
2395+ void error(String message, String textFound, String textExpected)
2396+ throws java.lang.Exception
2397+ {
2398+ if (textFound != null) {
2399+ message = message + " (found \"" + textFound + "\")";
2400+ }
2401+ if (textExpected != null) {
2402+ message = message + " (expected \"" + textExpected + "\")";
2403+ }
2404+ if (this.handler != null) {
2405+ String uri = null;
2406+
2407+ if (this.externalEntity != null) {
2408+ uri = this.externalEntity.getURL().toString();
2409+ }
2410+ this.handler.error(message, uri, this.line, this.column);
2411+ }
2412+ }
2413+
2414+ /**
2415+ * Report a serious error.
2416+ *
2417+ * @param message
2418+ * The error message.
2419+ * @param textFound
2420+ * The text that caused the error (or null).
2421+ */
2422+ void error(String message, char textFound, String textExpected)
2423+ throws java.lang.Exception
2424+ {
2425+ error(message, new Character(textFound).toString(), textExpected);
2426+ }
2427+
2428+ //////////////////////////////////////////////////////////////////////
2429+ // Major syntactic productions.
2430+ //////////////////////////////////////////////////////////////////////
2431+
2432+ /**
2433+ * Parse an XML document.
2434+ *
2435+ * <pre>
2436+ *
2437+ *
2438+ *
2439+ * [1] document ::= prolog element Misc*
2440+ *
2441+ *
2442+ *
2443+ * </pre>
2444+ *
2445+ * <p>
2446+ * This is the top-level parsing function for a single XML document. As a
2447+ * minimum, a well-formed document must have a document element, and a valid
2448+ * document must have a prolog as well.
2449+ */
2450+ void parseDocument() throws java.lang.Exception
2451+ {
2452+ char c;
2453+
2454+ parseProlog();
2455+ require('<');
2456+ parseElement();
2457+ try {
2458+ parseMisc(); //skip all white, PIs, and comments
2459+ c = readCh(); //if this doesn't throw an exception...
2460+ error("unexpected characters after document end", c, null);
2461+ } catch (EOFException e) {
2462+ return;
2463+ }
2464+ }
2465+
2466+ /**
2467+ * Skip a comment.
2468+ *
2469+ * <pre>
2470+ *
2471+ *
2472+ *
2473+ * [18] Comment ::= '&lt;!--' ((Char - '-') | ('-' (Char - '-')))* &quot;--&gt;&quot;
2474+ *
2475+ *
2476+ *
2477+ * </pre>
2478+ *
2479+ * <p>
2480+ * (The <code>&lt;!--</code> has already been read.)
2481+ */
2482+ void parseComment() throws java.lang.Exception
2483+ {
2484+ skipUntil("-->");
2485+ }
2486+
2487+ /**
2488+ * Parse a processing instruction and do a call-back.
2489+ *
2490+ * <pre>
2491+ *
2492+ *
2493+ *
2494+ * [19] PI ::= '&lt;?' Name (S (Char* - (Char* '?&gt;' Char*)))? '?&gt;'
2495+ *
2496+ *
2497+ *
2498+ * </pre>
2499+ *
2500+ * <p>
2501+ * (The <code>&lt;?</code> has already been read.)
2502+ * <p>
2503+ * An XML processing instruction <em>must</em> begin with a Name, which is
2504+ * the instruction's target.
2505+ */
2506+ void parsePI() throws java.lang.Exception
2507+ {
2508+ String name;
2509+
2510+ name = readNmtoken(true);
2511+ if (!tryRead("?>")) {
2512+ requireWhitespace();
2513+ parseUntil("?>");
2514+ }
2515+ if (this.handler != null) {
2516+ this.handler.processingInstruction(name, dataBufferToString());
2517+ }
2518+ }
2519+
2520+ /**
2521+ * Parse a CDATA marked section.
2522+ *
2523+ * <pre>
2524+ *
2525+ *
2526+ *
2527+ * [20] CDSect ::= CDStart CData CDEnd
2528+ * [21] CDStart ::= '&lt;![CDATA['
2529+ * [22] CData ::= (Char* - (Char* ']]&gt;' Char*))
2530+ * [23] CDEnd ::= ']]&gt;'
2531+ *
2532+ *
2533+ *
2534+ * </pre>
2535+ *
2536+ * <p>
2537+ * (The '&lt;![CDATA[' has already been read.)
2538+ * <p>
2539+ * Note that this just appends characters to the dataBuffer, without
2540+ * actually generating an event.
2541+ */
2542+ void parseCDSect() throws java.lang.Exception
2543+ {
2544+ parseUntil("]]>");
2545+ }
2546+
2547+ /**
2548+ * Parse the prolog of an XML document.
2549+ *
2550+ * <pre>
2551+ *
2552+ *
2553+ *
2554+ * [24] prolog ::= XMPDecl? Misc* (Doctypedecl Misc*)?
2555+ *
2556+ *
2557+ *
2558+ * </pre>
2559+ *
2560+ * <p>
2561+ * There are a couple of tricks here. First, it is necessary to declare the
2562+ * XML default attributes after the DTD (if present) has been read. Second,
2563+ * it is not possible to expand general references in attribute value
2564+ * literals until after the entire DTD (if present) has been parsed.
2565+ * <p>
2566+ * We do not look for the XML declaration here, because it is handled by
2567+ * pushURL().
2568+ *
2569+ * @see pushURL
2570+ */
2571+ void parseProlog() throws java.lang.Exception
2572+ {
2573+ parseMisc();
2574+
2575+ if (tryRead("<!DOCTYPE")) {
2576+ parseDoctypedecl();
2577+ parseMisc();
2578+ }
2579+ }
2580+
2581+ /**
2582+ * Parse the XML declaration.
2583+ *
2584+ * <pre>
2585+ *
2586+ *
2587+ *
2588+ * [25] XMPDecl ::= '&lt;?xml' VersionInfo EncodingDecl? SDDecl? S? '?&gt;'
2589+ * [26] VersionInfo ::= S 'version' Eq ('&quot;1.0&quot;' | &quot;'1.0'&quot;)
2590+ * [33] SDDecl ::= S 'standalone' Eq &quot;'&quot; ('yes' | 'no') &quot;'&quot;
2591+ * | S 'standalone' Eq '&quot;' (&quot;yes&quot; | &quot;no&quot;) '&quot;'
2592+ * [78] EncodingDecl ::= S 'encoding' Eq QEncoding
2593+ *
2594+ *
2595+ *
2596+ * </pre>
2597+ *
2598+ * <p>
2599+ * ([80] to [82] are also significant.)
2600+ * <p>
2601+ * (The <code>&lt;?xml</code> and whitespace have already been read.)
2602+ *
2603+ * @see #parseTextDecl
2604+ * @see #checkEncoding
2605+ */
2606+ void parseXMPDecl(boolean ignoreEncoding) throws java.lang.Exception
2607+ {
2608+ String version;
2609+ String encodingName = null;
2610+ // Read the version.
2611+ require("version");
2612+ parseEq();
2613+ version = readLiteral(0);
2614+ if (!version.equals("1.0")) {
2615+ error("unsupported XML version", version, "1.0");
2616+ }
2617+
2618+ // Try reading an encoding declaration.
2619+ skipWhitespace();
2620+ if (tryRead("encoding")) {
2621+ parseEq();
2622+ encodingName = readLiteral(0);
2623+ checkEncoding(encodingName, ignoreEncoding);
2624+ }
2625+
2626+ // Try reading a standalone declaration
2627+ skipWhitespace();
2628+ if (tryRead("standalone")) {
2629+ parseEq();
2630+ readLiteral(0);
2631+ }
2632+
2633+ skipWhitespace();
2634+ require("?>");
2635+ }
2636+
2637+ /**
2638+ * Parse the Encoding PI.
2639+ *
2640+ * <pre>
2641+ *
2642+ *
2643+ *
2644+ * [78] EncodingDecl ::= S 'encoding' Eq QEncoding
2645+ * [79] EncodingPI ::= '&lt;?xml' S 'encoding' Eq QEncoding S? '?&gt;'
2646+ * [80] QEncoding ::= '&quot;' Encoding '&quot;' | &quot;'&quot; Encoding &quot;'&quot;
2647+ * [81] Encoding ::= LatinName
2648+ * [82] LatinName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
2649+ *
2650+ *
2651+ *
2652+ * </pre>
2653+ *
2654+ * <p>
2655+ * (The <code>&lt;?xml</code>' and whitespace have already been read.)
2656+ *
2657+ * @see #parseXMPDecl
2658+ * @see #checkEncoding
2659+ */
2660+ void parseTextDecl(boolean ignoreEncoding) throws java.lang.Exception
2661+ {
2662+ String encodingName = null;
2663+
2664+ // Read an optional version.
2665+ if (tryRead("version")) {
2666+ String version;
2667+ parseEq();
2668+ version = readLiteral(0);
2669+ if (!version.equals("1.0")) {
2670+ error("unsupported XML version", version, "1.0");
2671+ }
2672+ requireWhitespace();
2673+ }
2674+
2675+ // Read the encoding.
2676+ require("encoding");
2677+ parseEq();
2678+ encodingName = readLiteral(0);
2679+ checkEncoding(encodingName, ignoreEncoding);
2680+
2681+ skipWhitespace();
2682+ require("?>");
2683+ }
2684+
2685+ /**
2686+ * Check that the encoding specified makes sense.
2687+ * <p>
2688+ * Compare what the author has specified in the XML declaration or encoding
2689+ * PI with what we have detected.
2690+ * <p>
2691+ * This is also important for distinguishing among the various 7- and 8-bit
2692+ * encodings, such as ISO-LATIN-1 (I cannot autodetect those).
2693+ *
2694+ * @param encodingName
2695+ * The name of the encoding specified by the user.
2696+ * @see #parseXMPDecl
2697+ * @see #parseTextDecl
2698+ */
2699+ void checkEncoding(String encodingName, boolean ignoreEncoding)
2700+ throws java.lang.Exception
2701+ {
2702+ encodingName = encodingName.toUpperCase();
2703+
2704+ if (ignoreEncoding) {
2705+ return;
2706+ }
2707+
2708+ switch (this.encoding) {
2709+ // 8-bit encodings
2710+ case ENCODING_UTF_8:
2711+ if (encodingName.equals("ISO-8859-1")) {
2712+ this.encoding = ENCODING_ISO_8859_1;
2713+ } else if (!encodingName.equals("UTF-8")) {
2714+ error("unsupported 8-bit encoding", encodingName,
2715+ "UTF-8 or ISO-8859-1");
2716+ }
2717+ break;
2718+ // 16-bit encodings
2719+ case ENCODING_UCS_2_12:
2720+ case ENCODING_UCS_2_21:
2721+ if (!encodingName.equals("ISO-10646-UCS-2")
2722+ && !encodingName.equals("UTF-16")) {
2723+ error("unsupported 16-bit encoding", encodingName,
2724+ "ISO-10646-UCS-2");
2725+ }
2726+ break;
2727+ // 32-bit encodings
2728+ case ENCODING_UCS_4_1234:
2729+ case ENCODING_UCS_4_4321:
2730+ case ENCODING_UCS_4_2143:
2731+ case ENCODING_UCS_4_3412:
2732+ if (!encodingName.equals("ISO-10646-UCS-4")) {
2733+ error("unsupported 32-bit encoding", encodingName,
2734+ "ISO-10646-UCS-4");
2735+ }
2736+ }
2737+ }
2738+
2739+ /**
2740+ * Parse miscellaneous markup outside the document element and DOCTYPE
2741+ * declaration.
2742+ *
2743+ * <pre>
2744+ *
2745+ *
2746+ *
2747+ * [27] Misc ::= Comment | PI | S
2748+ *
2749+ *
2750+ *
2751+ * </pre>
2752+ */
2753+ void parseMisc() throws java.lang.Exception
2754+ {
2755+ while (true) {
2756+ skipWhitespace();
2757+ if (tryRead("<?")) {
2758+ parsePI();
2759+ } else if (tryRead("<!--")) {
2760+ parseComment();
2761+ } else {
2762+ return;
2763+ }
2764+ }
2765+ }
2766+
2767+ /**
2768+ * Parse a document type declaration.
2769+ *
2770+ * <pre>
2771+ *
2772+ *
2773+ *
2774+ * [28] doctypedecl ::= '&lt;!DOCTYPE' S Name (S ExternalID)? S?
2775+ * ('[' %markupdecl* ']' S?)? '&gt;'
2776+ *
2777+ *
2778+ *
2779+ * </pre>
2780+ *
2781+ * <p>
2782+ * (The <code>&lt;!DOCTYPE</code> has already been read.)
2783+ */
2784+ void parseDoctypedecl() throws java.lang.Exception
2785+ {
2786+ String doctypeName, ids[];
2787+
2788+ // Read the document type name.
2789+ requireWhitespace();
2790+ doctypeName = readNmtoken(true);
2791+
2792+ // Read the ExternalIDs.
2793+ skipWhitespace();
2794+ ids = readExternalIds(false);
2795+
2796+ // Look for a declaration subset.
2797+ skipWhitespace();
2798+ if (tryRead('[')) {
2799+
2800+ // loop until the subset ends
2801+ while (true) {
2802+ this.context = CONTEXT_DTD;
2803+ skipWhitespace();
2804+ this.context = CONTEXT_NONE;
2805+ if (tryRead(']')) {
2806+ break; // end of subset
2807+ }
2808+ this.context = CONTEXT_DTD;
2809+ parseMarkupdecl();
2810+ this.context = CONTEXT_NONE;
2811+ }
2812+ }
2813+
2814+ // Read the external subset, if any
2815+ if (ids[1] != null) {
2816+ pushURL("[external subset]", ids[0], ids[1], null, null, null);
2817+
2818+ // Loop until we end up back at '>'
2819+ while (true) {
2820+ this.context = CONTEXT_DTD;
2821+ skipWhitespace();
2822+ this.context = CONTEXT_NONE;
2823+ if (tryRead('>')) {
2824+ break;
2825+ }
2826+ this.context = CONTEXT_DTD;
2827+ parseMarkupdecl();
2828+ this.context = CONTEXT_NONE;
2829+ }
2830+ } else {
2831+ // No external subset.
2832+ skipWhitespace();
2833+ require('>');
2834+ }
2835+
2836+ if (this.handler != null) {
2837+ this.handler.doctypeDecl(doctypeName, ids[0], ids[1]);
2838+ }
2839+
2840+ // Expand general entities in
2841+ // default values of attributes.
2842+ // (Do this after the doctypeDecl
2843+ // event!).
2844+ // expandAttributeDefaultValues();
2845+ }
2846+
2847+ /**
2848+ * Parse a markup declaration in the internal or external DTD subset.
2849+ *
2850+ * <pre>
2851+ *
2852+ *
2853+ *
2854+ * [29] markupdecl ::= ( %elementdecl | %AttlistDecl | %EntityDecl |
2855+ * %NotationDecl | %PI | %S | %Comment |
2856+ * InternalPERef )
2857+ * [30] InternalPERef ::= PEReference
2858+ * [31] extSubset ::= (%markupdecl | %conditionalSect)*
2859+ *
2860+ *
2861+ *
2862+ * </pre>
2863+ */
2864+ void parseMarkupdecl() throws java.lang.Exception
2865+ {
2866+ if (tryRead("<!ELEMENT")) {
2867+ parseElementdecl();
2868+ } else if (tryRead("<!ATTLIST")) {
2869+ parseAttlistDecl();
2870+ } else if (tryRead("<!ENTITY")) {
2871+ parseEntityDecl();
2872+ } else if (tryRead("<!NOTATION")) {
2873+ parseNotationDecl();
2874+ } else if (tryRead("<?")) {
2875+ parsePI();
2876+ } else if (tryRead("<!--")) {
2877+ parseComment();
2878+ } else if (tryRead("<![")) {
2879+ parseConditionalSect();
2880+ } else {
2881+ error("expected markup declaration", null, null);
2882+ }
2883+ }
2884+
2885+ /**
2886+ * Parse an element, with its tags.
2887+ *
2888+ * <pre>
2889+ *
2890+ *
2891+ *
2892+ * [33] STag ::= '&lt;' Name (S Attribute)* S? '&gt;' [WFC: unique Att spec]
2893+ * [38] element ::= EmptyElement | STag content ETag
2894+ * [39] EmptyElement ::= '&lt;' Name (S Attribute)* S? '/&gt;'
2895+ * [WFC: unique Att spec]
2896+ *
2897+ *
2898+ *
2899+ * </pre>
2900+ *
2901+ * <p>
2902+ * (The '&lt;' has already been read.)
2903+ * <p>
2904+ * NOTE: this method actually chains onto parseContent(), if necessary, and
2905+ * parseContent() will take care of calling parseETag().
2906+ */
2907+ void parseElement() throws java.lang.Exception
2908+ {
2909+ String gi;
2910+ char c;
2911+ int oldElementContent = this.currentElementContent;
2912+ String oldElement = this.currentElement;
2913+
2914+ // This is the (global) counter for the
2915+ // array of specified attributes.
2916+ this.tagAttributePos = 0;
2917+
2918+ // Read the element type name.
2919+ gi = readNmtoken(true);
2920+
2921+ // Determine the current content type.
2922+ this.currentElement = gi;
2923+ this.currentElementContent = getElementContentType(gi);
2924+ if (this.currentElementContent == CONTENT_UNDECLARED) {
2925+ this.currentElementContent = CONTENT_ANY;
2926+ }
2927+
2928+ // Read the attributes, if any.
2929+ // After this loop, we should be just
2930+ // in front of the closing delimiter.
2931+ skipWhitespace();
2932+ c = readCh();
2933+ while (c != '/' && c != '>') {
2934+ unread(c);
2935+ parseAttribute(gi);
2936+ skipWhitespace();
2937+ c = readCh();
2938+ }
2939+ unread(c);
2940+
2941+ // Supply any defaulted attributes.
2942+ Enumeration<String> atts = declaredAttributes(gi);
2943+ if (atts != null) {
2944+ String aname;
2945+ loop: while (atts.hasMoreElements()) {
2946+ aname = atts.nextElement();
2947+ // See if it was specified.
2948+ for (int i = 0; i < this.tagAttributePos; i++) {
2949+ if (this.tagAttributes[i] == aname) {
2950+ continue loop;
2951+ }
2952+ }
2953+ // I guess not...
2954+ if (this.handler != null) {
2955+ this.handler.attribute(aname, getAttributeExpandedValue(gi,
2956+ aname), false);
2957+ }
2958+ }
2959+ }
2960+
2961+ // Figure out if this is a start tag
2962+ // or an empty element, and dispatch an
2963+ // event accordingly.
2964+ c = readCh();
2965+ switch (c) {
2966+ case '>':
2967+ if (this.handler != null) {
2968+ this.handler.startElement(gi);
2969+ }
2970+ parseContent();
2971+ break;
2972+ case '/':
2973+ require('>');
2974+ if (this.handler != null) {
2975+ this.handler.startElement(gi);
2976+ this.handler.endElement(gi);
2977+ }
2978+ break;
2979+ }
2980+
2981+ // Restore the previous state.
2982+ this.currentElement = oldElement;
2983+ this.currentElementContent = oldElementContent;
2984+ }
2985+
2986+ /**
2987+ * Parse an attribute assignment.
2988+ *
2989+ * <pre>
2990+ *
2991+ *
2992+ *
2993+ * [34] Attribute ::= Name Eq AttValue
2994+ *
2995+ *
2996+ *
2997+ * </pre>
2998+ *
2999+ * @param name
3000+ * The name of the attribute's element.
3001+ * @see XmlHandler#attribute
3002+ */
3003+ void parseAttribute(String name) throws java.lang.Exception
3004+ {
3005+ String aname;
3006+ int type;
3007+ String value;
3008+
3009+ // Read the attribute name.
3010+ aname = readNmtoken(true).intern();
3011+ type = getAttributeDefaultValueType(name, aname);
3012+
3013+ // Parse '='
3014+ parseEq();
3015+
3016+ // Read the value, normalizing whitespace
3017+ // if it is not CDATA.
3018+ if (type == ATTRIBUTE_CDATA || type == ATTRIBUTE_UNDECLARED) {
3019+ value = readLiteral(LIT_CHAR_REF | LIT_ENTITY_REF);
3020+ } else {
3021+ value = readLiteral(LIT_CHAR_REF | LIT_ENTITY_REF | LIT_NORMALIZE);
3022+ }
3023+
3024+ // Inform the handler about the
3025+ // attribute.
3026+ if (this.handler != null) {
3027+ this.handler.attribute(aname, value, true);
3028+ }
3029+ this.dataBufferPos = 0;
3030+
3031+ // Note that the attribute has been
3032+ // specified.
3033+ if (this.tagAttributePos == this.tagAttributes.length) {
3034+ String newAttrib[] = new String[this.tagAttributes.length * 2];
3035+ System.arraycopy(this.tagAttributes, 0, newAttrib, 0, this.tagAttributePos);
3036+ this.tagAttributes = newAttrib;
3037+ }
3038+ this.tagAttributes[this.tagAttributePos++] = aname;
3039+ }
3040+
3041+ /**
3042+ * Parse an equals sign surrounded by optional whitespace. [35] Eq ::= S?
3043+ * '=' S?
3044+ */
3045+ void parseEq() throws java.lang.Exception
3046+ {
3047+ skipWhitespace();
3048+ require('=');
3049+ skipWhitespace();
3050+ }
3051+
3052+ /**
3053+ * Parse an end tag. [36] ETag ::= ' </' Name S? '>' *NOTE: parseContent()
3054+ * chains to here.
3055+ */
3056+ void parseETag() throws java.lang.Exception
3057+ {
3058+ String name;
3059+ name = readNmtoken(true);
3060+ if (name != this.currentElement) {
3061+ error("mismatched end tag", name, this.currentElement);
3062+ }
3063+ skipWhitespace();
3064+ require('>');
3065+ if (this.handler != null) {
3066+ this.handler.endElement(name);
3067+ }
3068+ }
3069+
3070+ /**
3071+ * Parse the content of an element. [37] content ::= (element | PCData |
3072+ * Reference | CDSect | PI | Comment)* [68] Reference ::= EntityRef |
3073+ * CharRef
3074+ */
3075+ void parseContent() throws java.lang.Exception
3076+ {
3077+ char c;
3078+
3079+ while (true) {
3080+
3081+ switch (this.currentElementContent) {
3082+ case CONTENT_ANY:
3083+ case CONTENT_MIXED:
3084+ parsePCData();
3085+ break;
3086+ case CONTENT_ELEMENTS:
3087+ parseWhitespace();
3088+ break;
3089+ }
3090+
3091+ // Handle delimiters
3092+ c = readCh();
3093+ switch (c) {
3094+
3095+ case '&': // Found "&"
3096+ c = readCh();
3097+ if (c != '#') {
3098+ unread(c);
3099+ parseEntityRef(true);
3100+ }
3101+ break;
3102+
3103+ case '<': // Found "<"
3104+
3105+ c = readCh();
3106+ switch (c) {
3107+
3108+ case '!': // Found "<!"
3109+ c = readCh();
3110+ switch (c) {
3111+ case '-': // Found "<!-"
3112+ require('-');
3113+ parseComment();
3114+ break;
3115+ case '[': // Found "<!["
3116+ require("CDATA[");
3117+ parseCDSect();
3118+ break;
3119+ default:
3120+ error("expected comment or CDATA section",
3121+ c, null);
3122+ break;
3123+ }
3124+ break;
3125+
3126+ case '?': // Found "<?"
3127+ dataBufferFlush();
3128+ parsePI();
3129+ break;
3130+
3131+ case '/': // Found "</"
3132+ dataBufferFlush();
3133+ parseETag();
3134+ return;
3135+
3136+ default: // Found "<" followed by something else
3137+ dataBufferFlush();
3138+ unread(c);
3139+ parseElement();
3140+ break;
3141+ }
3142+ }
3143+ }
3144+ }
3145+
3146+ /**
3147+ * Parse an element type declaration. [40] elementdecl ::= ' <!ELEMENT' S
3148+ * %Name S (%S S)? %contentspec S? '>' [VC: Unique Element Declaration]
3149+ * *NOTE: the ' <!ELEMENT' has already been read.
3150+ */
3151+ void parseElementdecl() throws java.lang.Exception
3152+ {
3153+ String name;
3154+
3155+ requireWhitespace();
3156+ // Read the element type name.
3157+ name = readNmtoken(true);
3158+
3159+ requireWhitespace();
3160+ // Read the content model.
3161+ parseContentspec(name);
3162+
3163+ skipWhitespace();
3164+ require('>');
3165+ }
3166+
3167+ /**
3168+ * Content specification. [41] contentspec ::= 'EMPTY' | 'ANY' | Mixed |
3169+ * elements
3170+ */
3171+ void parseContentspec(String name) throws java.lang.Exception
3172+ {
3173+ if (tryRead("EMPTY")) {
3174+ setElement(name, CONTENT_EMPTY, null, null);
3175+ return;
3176+ } else if (tryRead("ANY")) {
3177+ setElement(name, CONTENT_ANY, null, null);
3178+ return;
3179+ } else {
3180+ require('(');
3181+ dataBufferAppend('(');
3182+ skipWhitespace();
3183+ if (tryRead("#PCDATA")) {
3184+ dataBufferAppend("#PCDATA");
3185+ parseMixed();
3186+ setElement(name, CONTENT_MIXED, dataBufferToString(), null);
3187+ } else {
3188+ parseElements();
3189+ setElement(name, CONTENT_ELEMENTS, dataBufferToString(), null);
3190+ }
3191+ }
3192+ }
3193+
3194+ /**
3195+ * Parse an element-content model. [42] elements ::= (choice | seq) ('?' |
3196+ * '*' | '+')? [44] cps ::= S? %cp S? [45] choice ::= '(' S? %ctokplus (S?
3197+ * '|' S? %ctoks)* S? ')' [46] ctokplus ::= cps ('|' cps)+ [47] ctoks ::=
3198+ * cps ('|' cps)* [48] seq ::= '(' S? %stoks (S? ',' S? %stoks)* S? ')' [49]
3199+ * stoks ::= cps (',' cps)* *NOTE: the opening '(' and S have already been
3200+ * read.
3201+ */
3202+ void parseElements() throws java.lang.Exception
3203+ {
3204+ char c;
3205+ char sep;
3206+
3207+ // Parse the first content particle
3208+ skipWhitespace();
3209+ parseCp();
3210+
3211+ // Check for end or for a separator.
3212+ skipWhitespace();
3213+ c = readCh();
3214+ switch (c) {
3215+ case ')':
3216+ dataBufferAppend(')');
3217+ c = readCh();
3218+ switch (c) {
3219+ case '*':
3220+ case '+':
3221+ case '?':
3222+ dataBufferAppend(c);
3223+ break;
3224+ default:
3225+ unread(c);
3226+ }
3227+ return;
3228+ case ',': // Register the separator.
3229+ case '|':
3230+ sep = c;
3231+ dataBufferAppend(c);
3232+ break;
3233+ default:
3234+ error("bad separator in content model", c, null);
3235+ return;
3236+ }
3237+
3238+ // Parse the rest of the content model.
3239+ while (true) {
3240+ skipWhitespace();
3241+ parseCp();
3242+ skipWhitespace();
3243+ c = readCh();
3244+ if (c == ')') {
3245+ dataBufferAppend(')');
3246+ break;
3247+ } else if (c != sep) {
3248+ error("bad separator in content model", c, null);
3249+ return;
3250+ } else {
3251+ dataBufferAppend(c);
3252+ }
3253+ }
3254+
3255+ // Check for the occurrence indicator.
3256+ c = readCh();
3257+ switch (c) {
3258+ case '?':
3259+ case '*':
3260+ case '+':
3261+ dataBufferAppend(c);
3262+ return;
3263+ default:
3264+ unread(c);
3265+ return;
3266+ }
3267+ }
3268+
3269+ /**
3270+ * Parse a content particle. [43] cp ::= (Name | choice | seq) ('?' | '*' |
3271+ * '+') *NOTE: I actually use a slightly different production here: cp ::=
3272+ * (elements | (Name ('?' | '*' | '+')?))
3273+ */
3274+ void parseCp() throws java.lang.Exception
3275+ {
3276+ char c;
3277+
3278+ if (tryRead('(')) {
3279+ dataBufferAppend('(');
3280+ parseElements();
3281+ } else {
3282+ dataBufferAppend(readNmtoken(true));
3283+ c = readCh();
3284+ switch (c) {
3285+ case '?':
3286+ case '*':
3287+ case '+':
3288+ dataBufferAppend(c);
3289+ break;
3290+ default:
3291+ unread(c);
3292+ break;
3293+ }
3294+ }
3295+ }
3296+
3297+ /**
3298+ * Parse mixed content. [50] Mixed ::= '(' S? %( %'#PCDATA' (S? '|' S?
3299+ * %Mtoks)* ) S? ')*' | '(' S? %('#PCDATA') S? ')' [51] Mtoks ::= %Name (S?
3300+ * '|' S? %Name)* *NOTE: the S and '#PCDATA' have already been read.
3301+ */
3302+ void parseMixed() throws java.lang.Exception
3303+ {
3304+ // Check for PCDATA alone.
3305+ skipWhitespace();
3306+ if (tryRead(')')) {
3307+ dataBufferAppend(")*");
3308+ tryRead('*');
3309+ return;
3310+ }
3311+
3312+ // Parse mixed content.
3313+ skipWhitespace();
3314+ while (!tryRead(")*")) {
3315+ require('|');
3316+ dataBufferAppend('|');
3317+ skipWhitespace();
3318+ dataBufferAppend(readNmtoken(true));
3319+ skipWhitespace();
3320+ }
3321+ dataBufferAppend(")*");
3322+ }
3323+
3324+ /**
3325+ * Parse an attribute list declaration. [52] AttlistDecl ::= ' <!ATTLIST' S
3326+ * %Name S? %AttDef+ S? '>' *NOTE: the ' <!ATTLIST' has already been read.
3327+ */
3328+ void parseAttlistDecl() throws java.lang.Exception
3329+ {
3330+ String elementName;
3331+
3332+ requireWhitespace();
3333+ elementName = readNmtoken(true);
3334+ requireWhitespace();
3335+ while (!tryRead('>')) {
3336+ parseAttDef(elementName);
3337+ skipWhitespace();
3338+ }
3339+ }
3340+
3341+ /**
3342+ * Parse a single attribute definition. [53] AttDef ::= S %Name S %AttType S
3343+ * %Default
3344+ */
3345+ void parseAttDef(String elementName) throws java.lang.Exception
3346+ {
3347+ String name;
3348+ int type;
3349+ String enum_ = null;
3350+
3351+ // Read the attribute name.
3352+ name = readNmtoken(true);
3353+
3354+ // Read the attribute type.
3355+ requireWhitespace();
3356+ type = readAttType();
3357+
3358+ // Get the string of enumerated values
3359+ // if necessary.
3360+ if (type == ATTRIBUTE_ENUMERATED || type == ATTRIBUTE_NOTATION) {
3361+ enum_ = dataBufferToString();
3362+ }
3363+
3364+ // Read the default value.
3365+ requireWhitespace();
3366+ parseDefault(elementName, name, type, enum_);
3367+ }
3368+
3369+ /**
3370+ * Parse the attribute type. [54] AttType ::= StringType | TokenizedType |
3371+ * EnumeratedType [55] StringType ::= 'CDATA' [56] TokenizedType ::= 'ID' |
3372+ * 'IDREF' | 'IDREFS' | 'ENTITY' | 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS' [57]
3373+ * EnumeratedType ::= NotationType | Enumeration*
3374+ */
3375+ int readAttType() throws java.lang.Exception
3376+ {
3377+ String typeString;
3378+ Integer type;
3379+
3380+ if (tryRead('(')) {
3381+ parseEnumeration();
3382+ return ATTRIBUTE_ENUMERATED;
3383+ }
3384+ typeString = readNmtoken(true);
3385+ if (typeString.equals("NOTATION")) {
3386+ parseNotationType();
3387+ }
3388+ type = attributeTypeHash.get(typeString);
3389+ if (type == null) {
3390+ error("illegal attribute type", typeString, null);
3391+ return ATTRIBUTE_UNDECLARED;
3392+ }
3393+ return type.intValue();
3394+ }
3395+
3396+ /**
3397+ * Parse an enumeration. [60] Enumeration ::= '(' S? %Etoks (S? '|' S?
3398+ * %Etoks)* S? ')' [61] Etoks ::= %Nmtoken (S? '|' S? %Nmtoken)* *NOTE: the
3399+ * '(' has already been read.
3400+ */
3401+ void parseEnumeration() throws java.lang.Exception
3402+ {
3403+ dataBufferAppend('(');
3404+
3405+ // Read the first token.
3406+ skipWhitespace();
3407+ dataBufferAppend(readNmtoken(true));
3408+ // Read the remaining tokens.
3409+ skipWhitespace();
3410+ while (!tryRead(')')) {
3411+ require('|');
3412+ dataBufferAppend('|');
3413+ skipWhitespace();
3414+ dataBufferAppend(readNmtoken(true));
3415+ skipWhitespace();
3416+ }
3417+ dataBufferAppend(')');
3418+ }
3419+
3420+ /**
3421+ * Parse a notation type for an attribute. [58] NotationType ::= %'NOTATION'
3422+ * S '(' S? %Ntoks (S? '|' S? %Ntoks)* S? ')' [59] Ntoks ::= %Name (S? '|'
3423+ * S? %Name) *NOTE: the 'NOTATION' has already been read
3424+ */
3425+ void parseNotationType() throws java.lang.Exception
3426+ {
3427+ requireWhitespace();
3428+ require('(');
3429+
3430+ parseEnumeration();
3431+ }
3432+
3433+ /**
3434+ * Parse the default value for an attribute. [62] Default ::= '#REQUIRED' |
3435+ * '#IMPLIED' | ((%'#FIXED' S)? %AttValue
3436+ */
3437+ void parseDefault(String elementName, String name, int type, String enum_)
3438+ throws java.lang.Exception
3439+ {
3440+ int valueType = ATTRIBUTE_DEFAULT_SPECIFIED;
3441+ String value = null;
3442+ if (tryRead('#')) {
3443+ if (tryRead("FIXED")) {
3444+ valueType = ATTRIBUTE_DEFAULT_FIXED;
3445+ requireWhitespace();
3446+ this.context = CONTEXT_ATTRIBUTEVALUE;
3447+ value = readLiteral(LIT_CHAR_REF);
3448+ this.context = CONTEXT_DTD;
3449+ } else if (tryRead("REQUIRED")) {
3450+ valueType = ATTRIBUTE_DEFAULT_REQUIRED;
3451+ } else if (tryRead("IMPLIED")) {
3452+ valueType = ATTRIBUTE_DEFAULT_IMPLIED;
3453+ } else {
3454+ error("illegal keyword for attribute default value", null, null);
3455+ }
3456+ } else {
3457+ this.context = CONTEXT_ATTRIBUTEVALUE;
3458+ value = readLiteral(LIT_CHAR_REF);
3459+ this.context = CONTEXT_DTD;
3460+ }
3461+ setAttribute(elementName, name, type, enum_, value, valueType);
3462+ }
3463+
3464+ /**
3465+ * Parse a conditional section. [63] conditionalSect ::= includeSect ||
3466+ * ignoreSect [64] includeSect ::= ' <![' %'INCLUDE' '[' (%markupdecl*)*
3467+ * ']]>' [65] ignoreSect ::= ' <![' %'IGNORE' '[' ignoreSectContents* ']]>'
3468+ * [66] ignoreSectContents ::= ((SkipLit | Comment | PI) -(Char* ']]>')) | ('
3469+ * <![' ignoreSectContents* ']]>') | (Char - (']' | [ <'"])) | (' <!' (Char -
3470+ * ('-' | '['))) *NOTE: the ' <![' has already been read.
3471+ */
3472+ void parseConditionalSect() throws java.lang.Exception
3473+ {
3474+ skipWhitespace();
3475+ if (tryRead("INCLUDE")) {
3476+ skipWhitespace();
3477+ require('[');
3478+ skipWhitespace();
3479+ while (!tryRead("]]>")) {
3480+ parseMarkupdecl();
3481+ skipWhitespace();
3482+ }
3483+ } else if (tryRead("IGNORE")) {
3484+ skipWhitespace();
3485+ require('[');
3486+ char c;
3487+ for (int nest = 1; nest > 0;) {
3488+ c = readCh();
3489+ switch (c) {
3490+ case '<':
3491+ if (tryRead("![")) {
3492+ nest++;
3493+ }
3494+ //$FALL-THROUGH$
3495+ case ']':
3496+ if (tryRead("]>")) {
3497+ nest--;
3498+ }
3499+ }
3500+ }
3501+ } else {
3502+ error("conditional section must begin with INCLUDE or IGNORE",
3503+ null, null);
3504+ }
3505+ }
3506+
3507+ /**
3508+ * Parse a reference. [69] EntityRef ::= '&' Name ';' *NOTE: the '&' has
3509+ * already been read.
3510+ *
3511+ * @param externalAllowed
3512+ * External entities are allowed here.
3513+ */
3514+ void parseEntityRef(boolean externalAllowed) throws java.lang.Exception
3515+ {
3516+ String name;
3517+
3518+ name = readNmtoken(true);
3519+ require(';');
3520+ switch (getEntityType(name)) {
3521+ case ENTITY_UNDECLARED:
3522+ error("reference to undeclared entity", name, null);
3523+ break;
3524+ case ENTITY_INTERNAL:
3525+ pushString(name, getEntityValue(name));
3526+ break;
3527+ case ENTITY_TEXT:
3528+ if (externalAllowed) {
3529+ pushURL(name, getEntityPublicId(name),
3530+ getEntitySystemId(name), null, null, null);
3531+ } else {
3532+ error("reference to external entity in attribute value.",
3533+ name, null);
3534+ }
3535+ break;
3536+ case ENTITY_NDATA:
3537+ if (externalAllowed) {
3538+ error("data entity reference in content", name, null);
3539+ } else {
3540+ error("reference to external entity in attribute value.",
3541+ name, null);
3542+ }
3543+ break;
3544+ }
3545+ }
3546+
3547+ /**
3548+ * Parse a parameter entity reference. [70] PEReference ::= '%' Name ';'
3549+ * *NOTE: the '%' has already been read.
3550+ */
3551+ void parsePEReference(boolean isEntityValue) throws java.lang.Exception
3552+ {
3553+ String name;
3554+
3555+ name = "%" + readNmtoken(true);
3556+ require(';');
3557+ switch (getEntityType(name)) {
3558+ case ENTITY_UNDECLARED:
3559+ error("reference to undeclared parameter entity", name, null);
3560+ break;
3561+ case ENTITY_INTERNAL:
3562+ if (isEntityValue) {
3563+ pushString(name, getEntityValue(name));
3564+ } else {
3565+ pushString(name, " " + getEntityValue(name) + ' ');
3566+ }
3567+ break;
3568+ case ENTITY_TEXT:
3569+ if (isEntityValue) {
3570+ pushString(null, " ");
3571+ }
3572+ pushURL(name, getEntityPublicId(name), getEntitySystemId(name),
3573+ null, null, null);
3574+ if (isEntityValue) {
3575+ pushString(null, " ");
3576+ }
3577+ break;
3578+ }
3579+ }
3580+
3581+ /**
3582+ * Parse an entity declaration. [71] EntityDecl ::= ' <!ENTITY' S %Name S
3583+ * %EntityDef S? '>' | ' <!ENTITY' S '%' S %Name S %EntityDef S? '>' [72]
3584+ * EntityDef ::= EntityValue | ExternalDef [73] ExternalDef ::= ExternalID
3585+ * %NDataDecl? [74] ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S
3586+ * PubidLiteral S SystemLiteral [75] NDataDecl ::= S %'NDATA' S %Name *NOTE:
3587+ * the ' <!ENTITY' has already been read.
3588+ */
3589+ void parseEntityDecl() throws java.lang.Exception
3590+ {
3591+ char c;
3592+ boolean peFlag = false;
3593+ String name, value, notationName, ids[];
3594+
3595+ // Check for a parameter entity.
3596+ requireWhitespace();
3597+ if (tryRead('%')) {
3598+ peFlag = true;
3599+ requireWhitespace();
3600+ }
3601+
3602+ // Read the entity name, and prepend
3603+ // '%' if necessary.
3604+ name = readNmtoken(true);
3605+ if (peFlag) {
3606+ name = "%" + name;
3607+ }
3608+
3609+ // Read the entity value.
3610+ requireWhitespace();
3611+ c = readCh();
3612+ unread(c);
3613+ if (c == '"' || c == '\'') {
3614+ // Internal entity.
3615+ this.context = CONTEXT_ENTITYVALUE;
3616+ value = readLiteral(LIT_CHAR_REF | LIT_PE_REF);
3617+ this.context = CONTEXT_DTD;
3618+ setInternalEntity(name, value);
3619+ } else {
3620+ // Read the external IDs
3621+ ids = readExternalIds(false);
3622+ if (ids[1] == null) {
3623+ error("system identifer missing", name, null);
3624+ }
3625+
3626+ // Check for NDATA declaration.
3627+ skipWhitespace();
3628+ if (tryRead("NDATA")) {
3629+ requireWhitespace();
3630+ notationName = readNmtoken(true);
3631+ setExternalDataEntity(name, ids[0], ids[1], notationName);
3632+ } else {
3633+ setExternalTextEntity(name, ids[0], ids[1]);
3634+ }
3635+ }
3636+
3637+ // Finish the declaration.
3638+ skipWhitespace();
3639+ require('>');
3640+ }
3641+
3642+ /**
3643+ * Parse a notation declaration. [81] NotationDecl ::= ' <!NOTATION' S %Name
3644+ * S %ExternalID S? '>' *NOTE: the ' <!NOTATION' has already been read.
3645+ */
3646+ void parseNotationDecl() throws java.lang.Exception
3647+ {
3648+ String nname, ids[];
3649+
3650+ requireWhitespace();
3651+ nname = readNmtoken(true);
3652+
3653+ requireWhitespace();
3654+
3655+ // Read the external identifiers.
3656+ ids = readExternalIds(true);
3657+ if (ids[0] == null && ids[1] == null) {
3658+ error("external identifer missing", nname, null);
3659+ }
3660+
3661+ // Register the notation.
3662+ setNotation(nname, ids[0], ids[1]);
3663+
3664+ skipWhitespace();
3665+ require('>');
3666+ }
3667+
3668+ /**
3669+ * Parse PCDATA.
3670+ *
3671+ * <pre>
3672+ *
3673+ *
3674+ *
3675+ * [16] PCData ::= [&circ;&lt;&amp;]*
3676+ *
3677+ *
3678+ *
3679+ * </pre>
3680+ *
3681+ * <p>
3682+ * The trick here is that the data stays in the dataBuffer without
3683+ * necessarily being converted to a string right away.
3684+ */
3685+ void parsePCData() throws java.lang.Exception
3686+ {
3687+ char c;
3688+
3689+ // Start with a little cheat -- in most
3690+ // cases, the entire sequence of
3691+ // character data will already be in
3692+ // the readBuffer; if not, fall through to
3693+ // the normal approach.
3694+ if (USE_CHEATS) {
3695+ int lineAugment = 0;
3696+ int columnAugment = 0;
3697+
3698+ for (int i = this.readBufferPos; i < this.readBufferLength; i++) {
3699+ switch (this.readBuffer[i]) {
3700+ case '\n':
3701+ lineAugment++;
3702+ columnAugment = 0;
3703+ break;
3704+ case '&':
3705+ case '<':
3706+ int start = this.readBufferPos;
3707+ columnAugment++;
3708+ this.readBufferPos = i;
3709+ if (lineAugment > 0) {
3710+ this.line += lineAugment;
3711+ this.column = columnAugment;
3712+ } else {
3713+ this.column += columnAugment;
3714+ }
3715+ dataBufferAppend(this.readBuffer, start, i - start);
3716+ return;
3717+ default:
3718+ columnAugment++;
3719+ }
3720+ }
3721+ }
3722+
3723+ // OK, the cheat didn't work; start over
3724+ // and do it by the book.
3725+ while (true) {
3726+ c = readCh();
3727+ switch (c) {
3728+ case '<':
3729+ case '&':
3730+ unread(c);
3731+ return;
3732+ default:
3733+ dataBufferAppend(c);
3734+ break;
3735+ }
3736+ }
3737+ }
3738+
3739+ //////////////////////////////////////////////////////////////////////
3740+ // High-level reading and scanning methods.
3741+ //////////////////////////////////////////////////////////////////////
3742+
3743+ /**
3744+ * Require whitespace characters. [1] S ::= (#x20 | #x9 | #xd | #xa)+
3745+ */
3746+ void requireWhitespace() throws java.lang.Exception
3747+ {
3748+ char c = readCh();
3749+ if (isWhitespace(c)) {
3750+ skipWhitespace();
3751+ } else {
3752+ error("whitespace expected", c, null);
3753+ }
3754+ }
3755+
3756+ /**
3757+ * Parse whitespace characters, and leave them in the data buffer.
3758+ */
3759+ void parseWhitespace() throws java.lang.Exception
3760+ {
3761+ char c = readCh();
3762+ while (isWhitespace(c)) {
3763+ dataBufferAppend(c);
3764+ c = readCh();
3765+ }
3766+ unread(c);
3767+ }
3768+
3769+ /**
3770+ * Skip whitespace characters. [1] S ::= (#x20 | #x9 | #xd | #xa)+
3771+ */
3772+ void skipWhitespace() throws java.lang.Exception
3773+ {
3774+ // Start with a little cheat. Most of
3775+ // the time, the white space will fall
3776+ // within the current read buffer; if
3777+ // not, then fall through.
3778+ if (USE_CHEATS) {
3779+ int lineAugment = 0;
3780+ int columnAugment = 0;
3781+
3782+ loop: for (int i = this.readBufferPos; i < this.readBufferLength; i++) {
3783+ switch (this.readBuffer[i]) {
3784+ case ' ':
3785+ case '\t':
3786+ case '\r':
3787+ columnAugment++;
3788+ break;
3789+ case '\n':
3790+ lineAugment++;
3791+ columnAugment = 0;
3792+ break;
3793+ case '%':
3794+ if (this.context == CONTEXT_DTD
3795+ || this.context == CONTEXT_ENTITYVALUE) {
3796+ break loop;
3797+ } // else fall through...
3798+ //$FALL-THROUGH$
3799+ default:
3800+ this.readBufferPos = i;
3801+ if (lineAugment > 0) {
3802+ this.line += lineAugment;
3803+ this.column = columnAugment;
3804+ } else {
3805+ this.column += columnAugment;
3806+ }
3807+ return;
3808+ }
3809+ }
3810+ }
3811+
3812+ // OK, do it by the book.
3813+ char c = readCh();
3814+ while (isWhitespace(c)) {
3815+ c = readCh();
3816+ }
3817+ unread(c);
3818+ }
3819+
3820+ /**
3821+ * Read a name or name token. [5] Name ::= (Letter | '_' | ':') (NameChar)*
3822+ * [7] Nmtoken ::= (NameChar)+ *NOTE: [6] is implemented implicitly where
3823+ * required.
3824+ */
3825+ String readNmtoken(boolean isName) throws java.lang.Exception
3826+ {
3827+ char c;
3828+
3829+ if (USE_CHEATS) {
3830+ loop: for (int i = this.readBufferPos; i < this.readBufferLength; i++) {
3831+ switch (this.readBuffer[i]) {
3832+ case '%':
3833+ if (this.context == CONTEXT_DTD
3834+ || this.context == CONTEXT_ENTITYVALUE) {
3835+ break loop;
3836+ } // else fall through...
3837+ //$FALL-THROUGH$
3838+ case '<':
3839+ case '>':
3840+ case '&':
3841+ case ',':
3842+ case '|':
3843+ case '*':
3844+ case '+':
3845+ case '?':
3846+ case ')':
3847+ case '=':
3848+ case '\'':
3849+ case '"':
3850+ case '[':
3851+ case ' ':
3852+ case '\t':
3853+ case '\r':
3854+ case '\n':
3855+ case ';':
3856+ case '/':
3857+ case '#':
3858+ int start = this.readBufferPos;
3859+ if (i == start) {
3860+ error("name expected", this.readBuffer[i], null);
3861+ }
3862+ this.readBufferPos = i;
3863+ return intern(this.readBuffer, start, i - start);
3864+ }
3865+ }
3866+ }
3867+
3868+ this.nameBufferPos = 0;
3869+
3870+ // Read the first character.
3871+ while (true) {
3872+ c = readCh();
3873+ switch (c) {
3874+ case '%':
3875+ case '<':
3876+ case '>':
3877+ case '&':
3878+ case ',':
3879+ case '|':
3880+ case '*':
3881+ case '+':
3882+ case '?':
3883+ case ')':
3884+ case '=':
3885+ case '\'':
3886+ case '"':
3887+ case '[':
3888+ case ' ':
3889+ case '\t':
3890+ case '\n':
3891+ case '\r':
3892+ case ';':
3893+ case '/':
3894+ unread(c);
3895+ if (this.nameBufferPos == 0) {
3896+ error("name expected", null, null);
3897+ }
3898+ String s = intern(this.nameBuffer, 0, this.nameBufferPos);
3899+ this.nameBufferPos = 0;
3900+ return s;
3901+ default:
3902+ this.nameBuffer = (char[]) extendArray(this.nameBuffer,
3903+ this.nameBuffer.length, this.nameBufferPos);
3904+ this.nameBuffer[this.nameBufferPos++] = c;
3905+ }
3906+ }
3907+ }
3908+
3909+ /**
3910+ * Read a literal. [10] AttValue ::= '"' ([^ <&"] | Reference)* '"' | "'"
3911+ * ([^ <&'] | Reference)* "'" [11] SystemLiteral ::= '"' URLchar* '"' | "'"
3912+ * (URLchar - "'")* "'" [13] PubidLiteral ::= '"' PubidChar* '"' | "'"
3913+ * (PubidChar - "'")* "'" [9] EntityValue ::= '"' ([^%&"] | PEReference |
3914+ * Reference)* '"' | "'" ([^%&'] | PEReference | Reference)* "'"
3915+ */
3916+ String readLiteral(int flags) throws java.lang.Exception
3917+ {
3918+ char delim, c;
3919+ int startLine = this.line;
3920+
3921+ // Find the delimiter.
3922+ delim = readCh();
3923+ if (delim != '"' && delim != '\'' && delim != (char) 0) {
3924+ error("expected '\"' or \"'\"", delim, null);
3925+ return null;
3926+ }
3927+
3928+ // Read the literal.
3929+ try {
3930+ c = readCh();
3931+
3932+ loop: while (c != delim) {
3933+ switch (c) {
3934+ // Literals never have line ends
3935+ case '\n':
3936+ case '\r':
3937+ c = ' ';
3938+ break;
3939+ // References may be allowed
3940+ case '&':
3941+ if ((flags & LIT_CHAR_REF) > 0) {
3942+ c = readCh();
3943+ if (c == '#') {
3944+ c = readCh();
3945+ continue loop; // check the next character
3946+ } else if ((flags & LIT_ENTITY_REF) > 0) {
3947+ unread(c);
3948+ parseEntityRef(false);
3949+ c = readCh();
3950+ continue loop;
3951+ } else {
3952+ dataBufferAppend('&');
3953+ }
3954+ }
3955+ break;
3956+
3957+ default:
3958+ break;
3959+ }
3960+ dataBufferAppend(c);
3961+ c = readCh();
3962+ }
3963+ } catch (EOFException e) {
3964+ error("end of input while looking for delimiter (started on line "
3965+ + startLine + ')', null, new Character(delim).toString());
3966+ }
3967+
3968+ // Normalise whitespace if necessary.
3969+ if ((flags & LIT_NORMALIZE) > 0) {
3970+ dataBufferNormalize();
3971+ }
3972+
3973+ // Return the value.
3974+ return dataBufferToString();
3975+ }
3976+
3977+ /**
3978+ * Try reading external identifiers.
3979+ * <p>
3980+ * The system identifier is not required for notations.
3981+ *
3982+ * @param inNotation
3983+ * Are we in a notation?
3984+ * @return A two-member String array containing the identifiers.
3985+ */
3986+ String[] readExternalIds(boolean inNotation) throws java.lang.Exception
3987+ {
3988+ String ids[] = new String[2];
3989+
3990+ if (tryRead("PUBLIC")) {
3991+ requireWhitespace();
3992+ ids[0] = readLiteral(LIT_NORMALIZE); // public id
3993+ if (inNotation) {
3994+ skipWhitespace();
3995+ if (tryRead('"') || tryRead('\'')) {
3996+ ids[1] = readLiteral(0);
3997+ }
3998+ } else {
3999+ requireWhitespace();
4000+ ids[1] = readLiteral(0); // system id
4001+ }
4002+ } else if (tryRead("SYSTEM")) {
4003+ requireWhitespace();
4004+ ids[1] = readLiteral(0); // system id
4005+ }
4006+
4007+ return ids;
4008+ }
4009+
4010+ /**
4011+ * Test if a character is whitespace.
4012+ *
4013+ * <pre>
4014+ *
4015+ *
4016+ *
4017+ * [1] S ::= (#x20 | #x9 | #xd | #xa)+
4018+ *
4019+ *
4020+ *
4021+ * </pre>
4022+ *
4023+ * @param c
4024+ * The character to test.
4025+ * @return true if the character is whitespace.
4026+ */
4027+ final boolean isWhitespace(char c)
4028+ {
4029+ switch (c) {
4030+ case 0x20:
4031+ case 0x09:
4032+ case 0x0d:
4033+ case 0x0a:
4034+ return true;
4035+ default:
4036+ return false;
4037+ }
4038+ }
4039+
4040+ //////////////////////////////////////////////////////////////////////
4041+ // Utility routines.
4042+ //////////////////////////////////////////////////////////////////////
4043+
4044+ /**
4045+ * Add a character to the data buffer.
4046+ */
4047+ void dataBufferAppend(char c)
4048+ {
4049+ // Expand buffer if necessary.
4050+ this.dataBuffer = (char[]) extendArray(this.dataBuffer, this.dataBuffer.length,
4051+ this.dataBufferPos);
4052+ this.dataBuffer[this.dataBufferPos++] = c;
4053+ }
4054+
4055+ /**
4056+ * Add a string to the data buffer.
4057+ */
4058+ void dataBufferAppend(String s)
4059+ {
4060+ dataBufferAppend(s.toCharArray(), 0, s.length());
4061+ }
4062+
4063+ /**
4064+ * Append (part of) a character array to the data buffer.
4065+ */
4066+ void dataBufferAppend(char ch[], int start, int length)
4067+ {
4068+ this.dataBuffer = (char[]) extendArray(this.dataBuffer, this.dataBuffer.length,
4069+ this.dataBufferPos + length);
4070+ System.arraycopy(ch, start, this.dataBuffer,
4071+ this.dataBufferPos, length);
4072+ this.dataBufferPos += length;
4073+ }
4074+
4075+ /**
4076+ * Normalise whitespace in the data buffer.
4077+ */
4078+ void dataBufferNormalize()
4079+ {
4080+ int i = 0;
4081+ int j = 0;
4082+ int end = this.dataBufferPos;
4083+
4084+ // Skip whitespace at the start.
4085+ while (j < end && isWhitespace(this.dataBuffer[j])) {
4086+ j++;
4087+ }
4088+
4089+ // Skip whitespace at the end.
4090+ while (end > j && isWhitespace(this.dataBuffer[end - 1])) {
4091+ end--;
4092+ }
4093+
4094+ // Start copying to the left.
4095+ while (j < end) {
4096+
4097+ char c = this.dataBuffer[j++];
4098+
4099+ // Normalise all other whitespace to
4100+ // a single space.
4101+ if (isWhitespace(c)) {
4102+ while (j < end && isWhitespace(this.dataBuffer[j++])) {
4103+ }
4104+ this.dataBuffer[i++] = ' ';
4105+ this.dataBuffer[i++] = this.dataBuffer[j - 1];
4106+ } else {
4107+ this.dataBuffer[i++] = c;
4108+ }
4109+ }
4110+
4111+ // The new length is <= the old one.
4112+ this.dataBufferPos = i;
4113+ }
4114+
4115+ /**
4116+ * Convert the data buffer to a string.
4117+ *
4118+ * @param internFlag
4119+ * true if the contents should be interned.
4120+ * @see #intern(char[],int,int)
4121+ */
4122+ String dataBufferToString()
4123+ {
4124+ String s = new String(this.dataBuffer, 0, this.dataBufferPos);
4125+ this.dataBufferPos = 0;
4126+ return s;
4127+ }
4128+
4129+ /**
4130+ * Flush the contents of the data buffer to the handler, if appropriate, and
4131+ * reset the buffer for new input.
4132+ */
4133+ void dataBufferFlush() throws java.lang.Exception
4134+ {
4135+ if (this.dataBufferPos > 0) {
4136+ switch (this.currentElementContent) {
4137+ case CONTENT_UNDECLARED:
4138+ case CONTENT_EMPTY:
4139+ // do nothing
4140+ break;
4141+ case CONTENT_MIXED:
4142+ case CONTENT_ANY:
4143+ if (this.handler != null) {
4144+ this.handler.charData(this.dataBuffer, 0, this.dataBufferPos);
4145+ }
4146+ break;
4147+ case CONTENT_ELEMENTS:
4148+ if (this.handler != null) {
4149+ this.handler.ignorableWhitespace(this.dataBuffer, 0,
4150+ this.dataBufferPos);
4151+ }
4152+ break;
4153+ }
4154+ this.dataBufferPos = 0;
4155+ }
4156+ }
4157+
4158+ /**
4159+ * Require a string to appear, or throw an exception.
4160+ */
4161+ void require(String delim) throws java.lang.Exception
4162+ {
4163+ char ch[] = delim.toCharArray();
4164+ for (int i = 0; i < ch.length; i++) {
4165+ require(ch[i]);
4166+ }
4167+ }
4168+
4169+ /**
4170+ * Require a character to appear, or throw an exception.
4171+ */
4172+ void require(char delim) throws java.lang.Exception
4173+ {
4174+ char c = readCh();
4175+
4176+ if (c != delim) {
4177+ error("expected character", c, new Character(delim).toString());
4178+ }
4179+ }
4180+
4181+ /**
4182+ * Return an internalised version of a string.
4183+ * <p>
4184+ * &AElig;lfred uses this method to create an internalised version of all
4185+ * names and attribute values, so that it can test equality with
4186+ * <code>==</code> instead of <code>String.equals()</code>.
4187+ * <p>
4188+ * If you want to be able to test for equality in the same way, you can use
4189+ * this method to internalise your own strings first:
4190+ *
4191+ * <pre>
4192+ * String PARA = handler.intern(&quot;PARA&quot;);
4193+ * </pre>
4194+ *
4195+ * <p>
4196+ * Note that this will not return the same results as String.intern().
4197+ *
4198+ * @param s
4199+ * The string to internalise.
4200+ * @return An internalised version of the string.
4201+ * @see #intern(char[],int,int)
4202+ * @see java.lang.String#intern
4203+ */
4204+ public String intern(String s)
4205+ {
4206+ char ch[] = s.toCharArray();
4207+ return intern(ch, 0, ch.length);
4208+ }
4209+
4210+ /**
4211+ * Create an internalised string from a character array.
4212+ * <p>
4213+ * This is much more efficient than constructing a non-internalised string
4214+ * first, and then internalising it.
4215+ * <p>
4216+ * Note that this will not return the same results as String.intern().
4217+ *
4218+ * @param ch
4219+ * an array of characters for building the string.
4220+ * @param start
4221+ * the starting position in the array.
4222+ * @param length
4223+ * the number of characters to place in the string.
4224+ * @return an internalised string.
4225+ * @see #intern(String)
4226+ * @see java.lang.String#intern
4227+ */
4228+ public String intern(char ch[], int start, int length)
4229+ {
4230+ int index;
4231+ int hash = 0;
4232+
4233+ // Generate a hash code.
4234+ for (int i = start; i < start + length; i++) {
4235+ hash = ((hash << 1) & 0xffffff) + ch[i];
4236+ }
4237+
4238+ hash = hash % SYMBOL_TABLE_LENGTH;
4239+
4240+ // Get the bucket.
4241+ Object bucket[] = (Object[]) this.symbolTable[hash];
4242+ if (bucket == null) {
4243+ this.symbolTable[hash] = bucket = new Object[8];
4244+ }
4245+
4246+ // Search for a matching tuple, and
4247+ // return the string if we find one.
4248+ for (index = 0; index < bucket.length; index += 2) {
4249+ char chFound[] = (char[]) bucket[index];
4250+
4251+ // Stop when we hit a null index.
4252+ if (chFound == null) {
4253+ break;
4254+ }
4255+
4256+ // If they're the same length,
4257+ // check for a match.
4258+ // If the loop finishes, 'index' will
4259+ // contain the current bucket
4260+ // position.
4261+ if (chFound.length == length) {
4262+ for (int i = 0; i < chFound.length; i++) {
4263+ // Stop if there are no more tuples.
4264+ if (ch[start + i] != chFound[i]) {
4265+ break;
4266+ } else if (i == length - 1) {
4267+ // That's it, we have a match!
4268+ return (String) bucket[index + 1];
4269+ }
4270+ }
4271+ }
4272+ }
4273+
4274+ // Not found -- we'll have to add it.
4275+
4276+ // Do we have to grow the bucket?
4277+ bucket = (Object[]) extendArray(bucket, bucket.length, index);
4278+
4279+ // OK, add it to the end of the
4280+ // bucket.
4281+ String s = new String(ch, start, length);
4282+ bucket[index] = s.toCharArray();
4283+ bucket[index + 1] = s;
4284+ this.symbolTable[hash] = bucket;
4285+ return s;
4286+ }
4287+
4288+ /**
4289+ * Ensure the capacity of an array, allocating a new one if necessary.
4290+ */
4291+ Object extendArray(Object array, int currentSize, int requiredSize)
4292+ {
4293+ if (requiredSize < currentSize) {
4294+ return array;
4295+ }
4296+ Object newArray = null;
4297+ int newSize = currentSize * 2;
4298+
4299+ if (newSize <= requiredSize) {
4300+ newSize = requiredSize + 1;
4301+ }
4302+
4303+ if (array instanceof char[]) {
4304+ newArray = new char[currentSize * 2];
4305+ } else if (array instanceof Object[]) {
4306+ newArray = new Object[currentSize * 2];
4307+ }
4308+
4309+ System.arraycopy(array, 0, newArray, 0, currentSize);
4310+ return newArray;
4311+ }
4312+
4313+ //////////////////////////////////////////////////////////////////////
4314+ // XML query routines.
4315+ //////////////////////////////////////////////////////////////////////
4316+
4317+ //
4318+ // Elements
4319+ //
4320+
4321+ /**
4322+ * Get the declared elements for an XML document.
4323+ * <p>
4324+ * The results will be valid only after the DTD (if any) has been parsed.
4325+ *
4326+ * @return An enumeration of all element types declared for this document
4327+ * (as Strings).
4328+ * @see #getElementContentType
4329+ * @see #getElementContentModel
4330+ */
4331+ public Enumeration<String> declaredElements()
4332+ {
4333+ return this.elementInfo.keys();
4334+ }
4335+
4336+ /**
4337+ * Look up the content type of an element.
4338+ *
4339+ * @param name
4340+ * The element type name.
4341+ * @return An integer constant representing the content type.
4342+ * @see #getElementContentModel
4343+ * @see #CONTENT_UNDECLARED
4344+ * @see #CONTENT_ANY
4345+ * @see #CONTENT_EMPTY
4346+ * @see #CONTENT_MIXED
4347+ * @see #CONTENT_ELEMENTS
4348+ */
4349+ public int getElementContentType(String name)
4350+ {
4351+ Object element[] = this.elementInfo.get(name);
4352+ if (element == null) {
4353+ return CONTENT_UNDECLARED;
4354+ }
4355+ return ((Integer) element[0]).intValue();
4356+ }
4357+
4358+ /**
4359+ * Look up the content model of an element.
4360+ * <p>
4361+ * The result will always be null unless the content type is
4362+ * CONTENT_ELEMENTS or CONTENT_MIXED.
4363+ *
4364+ * @param name
4365+ * The element type name.
4366+ * @return The normalised content model, as a string.
4367+ * @see #getElementContentType
4368+ */
4369+ public String getElementContentModel(String name)
4370+ {
4371+ Object element[] = this.elementInfo.get(name);
4372+ if (element == null) {
4373+ return null;
4374+ }
4375+ return (String) element[1];
4376+ }
4377+
4378+ /**
4379+ * Register an element. Array format: element type attribute hash table
4380+ */
4381+ void setElement(String name, int contentType, String contentModel,
4382+ Hashtable<String, Object[]> attributes) throws java.lang.Exception
4383+ {
4384+ Object element[];
4385+
4386+ // Try looking up the element
4387+ element = this.elementInfo.get(name);
4388+
4389+ // Make a new one if necessary.
4390+ if (element == null) {
4391+ element = new Object[3];
4392+ element[0] = new Integer(CONTENT_UNDECLARED);
4393+ element[1] = null;
4394+ element[2] = null;
4395+ } else if (contentType != CONTENT_UNDECLARED
4396+ && ((Integer) element[0]).intValue() != CONTENT_UNDECLARED) {
4397+ error("multiple declarations for element type", name, null);
4398+ return;
4399+ }
4400+
4401+ // Insert the content type, if any.
4402+ if (contentType != CONTENT_UNDECLARED) {
4403+ element[0] = new Integer(contentType);
4404+ }
4405+
4406+ // Insert the content model, if any.
4407+ if (contentModel != null) {
4408+ element[1] = contentModel;
4409+ }
4410+
4411+ // Insert the attributes, if any.
4412+ if (attributes != null) {
4413+ element[2] = attributes;
4414+ }
4415+
4416+ // Save the element info.
4417+ this.elementInfo.put(name, element);
4418+ }
4419+
4420+ /**
4421+ * Look up the attribute hash table for an element. The hash table is the
4422+ * second item in the element array.
4423+ */
4424+ @SuppressWarnings("unchecked")
4425+ Hashtable<String, Object[]> getElementAttributes(String name)
4426+ {
4427+ Object element[] = this.elementInfo.get(name);
4428+ if (element == null) {
4429+ return null;
4430+ }
4431+ return (Hashtable<String, Object[]>) element[2];
4432+ }
4433+
4434+ //
4435+ // Attributes
4436+ //
4437+
4438+ /**
4439+ * Get the declared attributes for an element type.
4440+ *
4441+ * @param elname
4442+ * The name of the element type.
4443+ * @return An Enumeration of all the attributes declared for a specific
4444+ * element type. The results will be valid only after the DTD (if
4445+ * any) has been parsed.
4446+ * @see #getAttributeType
4447+ * @see #getAttributeEnumeration
4448+ * @see #getAttributeDefaultValueType
4449+ * @see #getAttributeDefaultValue
4450+ * @see #getAttributeExpandedValue
4451+ */
4452+ public Enumeration<String> declaredAttributes(String elname)
4453+ {
4454+ Hashtable<String, Object[]> attlist = getElementAttributes(elname);
4455+
4456+ if (attlist == null) {
4457+ return null;
4458+ }
4459+ return attlist.keys();
4460+ }
4461+
4462+ /**
4463+ * Retrieve the declared type of an attribute.
4464+ *
4465+ * @param name
4466+ * The name of the associated element.
4467+ * @param aname
4468+ * The name of the attribute.
4469+ * @return An integer constant representing the attribute type.
4470+ * @see #ATTRIBUTE_UNDECLARED
4471+ * @see #ATTRIBUTE_CDATA
4472+ * @see #ATTRIBUTE_ID
4473+ * @see #ATTRIBUTE_IDREF
4474+ * @see #ATTRIBUTE_IDREFS
4475+ * @see #ATTRIBUTE_ENTITY
4476+ * @see #ATTRIBUTE_ENTITIES
4477+ * @see #ATTRIBUTE_NMTOKEN
4478+ * @see #ATTRIBUTE_NMTOKENS
4479+ * @see #ATTRIBUTE_ENUMERATED
4480+ * @see #ATTRIBUTE_NOTATION
4481+ */
4482+ public int getAttributeType(String name, String aname)
4483+ {
4484+ Object attribute[] = getAttribute(name, aname);
4485+ if (attribute == null) {
4486+ return ATTRIBUTE_UNDECLARED;
4487+ }
4488+ return ((Integer) attribute[0]).intValue();
4489+ }
4490+
4491+ /**
4492+ * Retrieve the allowed values for an enumerated attribute type.
4493+ *
4494+ * @param name
4495+ * The name of the associated element.
4496+ * @param aname
4497+ * The name of the attribute.
4498+ * @return A string containing the token list.
4499+ * @see #ATTRIBUTE_ENUMERATED
4500+ * @see #ATTRIBUTE_NOTATION
4501+ */
4502+ public String getAttributeEnumeration(String name, String aname)
4503+ {
4504+ Object attribute[] = getAttribute(name, aname);
4505+ if (attribute == null) {
4506+ return null;
4507+ }
4508+ return (String) attribute[3];
4509+ }
4510+
4511+ /**
4512+ * Retrieve the default value of a declared attribute.
4513+ *
4514+ * @param name
4515+ * The name of the associated element.
4516+ * @param aname
4517+ * The name of the attribute.
4518+ * @return The default value, or null if the attribute was #IMPLIED or
4519+ * simply undeclared and unspecified.
4520+ * @see #getAttributeExpandedValue
4521+ */
4522+ public String getAttributeDefaultValue(String name, String aname)
4523+ {
4524+ Object attribute[] = getAttribute(name, aname);
4525+ if (attribute == null) {
4526+ return null;
4527+ }
4528+ return (String) attribute[1];
4529+ }
4530+
4531+ /**
4532+ * Retrieve the expanded value of a declared attribute.
4533+ * <p>
4534+ * All general entities will be expanded.
4535+ *
4536+ * @param name
4537+ * The name of the associated element.
4538+ * @param aname
4539+ * The name of the attribute.
4540+ * @return The expanded default value, or null if the attribute was #IMPLIED
4541+ * or simply undeclared
4542+ * @see #getAttributeDefaultValue
4543+ */
4544+ public String getAttributeExpandedValue(String name, String aname)
4545+ {
4546+ Object attribute[] = getAttribute(name, aname);
4547+ if (attribute == null) {
4548+ return null;
4549+ } else if (attribute[4] == null && attribute[1] != null) {
4550+ try {
4551+ pushString(null, (char) 0 + (String) attribute[1] + (char) 0);
4552+ attribute[4] = readLiteral(LIT_NORMALIZE | LIT_CHAR_REF
4553+ | LIT_ENTITY_REF);
4554+ } catch (Exception e) {
4555+ }
4556+ }
4557+ return (String) attribute[4];
4558+ }
4559+
4560+ /**
4561+ * Retrieve the default value type of a declared attribute.
4562+ *
4563+ * @see #ATTRIBUTE_DEFAULT_SPECIFIED
4564+ * @see #ATTRIBUTE_DEFAULT_IMPLIED
4565+ * @see #ATTRIBUTE_DEFAULT_REQUIRED
4566+ * @see #ATTRIBUTE_DEFAULT_FIXED
4567+ */
4568+ public int getAttributeDefaultValueType(String name, String aname)
4569+ {
4570+ Object attribute[] = getAttribute(name, aname);
4571+ if (attribute == null) {
4572+ return ATTRIBUTE_DEFAULT_UNDECLARED;
4573+ }
4574+ return ((Integer) attribute[2]).intValue();
4575+ }
4576+
4577+ /**
4578+ * Register an attribute declaration for later retrieval. Format: - String
4579+ * type - String default value - int value type
4580+ */
4581+ void setAttribute(String elName, String name, int type, String enumeration,
4582+ String value, int valueType) throws java.lang.Exception
4583+ {
4584+ Hashtable<String, Object[]> attlist;
4585+ Object attribute[];
4586+
4587+ // Create a new hashtable if necessary.
4588+ attlist = getElementAttributes(elName);
4589+ if (attlist == null) {
4590+ attlist = new Hashtable<String, Object[]>();
4591+ }
4592+
4593+ // Check that the attribute doesn't
4594+ // already exist!
4595+ if (attlist.get(name) != null) {
4596+ return;
4597+ }
4598+ attribute = new Object[5];
4599+ attribute[0] = new Integer(type);
4600+ attribute[1] = value;
4601+ attribute[2] = new Integer(valueType);
4602+ attribute[3] = enumeration;
4603+ attribute[4] = null;
4604+ attlist.put(name.intern(), attribute);
4605+
4606+ // Use CONTENT_UNDECLARED to avoid overwriting
4607+ // existing element declaration.
4608+ setElement(elName, CONTENT_UNDECLARED, null, attlist);
4609+ }
4610+
4611+ /**
4612+ * Retrieve the three-member array representing an attribute declaration.
4613+ */
4614+ Object[] getAttribute(String elName, String name)
4615+ {
4616+ Hashtable<String, Object[]> attlist;
4617+ Object attribute[];
4618+
4619+ attlist = getElementAttributes(elName);
4620+ if (attlist == null) {
4621+ return null;
4622+ }
4623+
4624+ attribute = attlist.get(name);
4625+ return attribute;
4626+ }
4627+
4628+ //
4629+ // Entities
4630+ //
4631+
4632+ /**
4633+ * Get declared entities.
4634+ *
4635+ * @return An Enumeration of all the entities declared for this XML
4636+ * document. The results will be valid only after the DTD (if any)
4637+ * has been parsed.
4638+ * @see #getEntityType
4639+ * @see #getEntityPublicId
4640+ * @see #getEntitySystemId
4641+ * @see #getEntityValue
4642+ * @see #getEntityNotationName
4643+ */
4644+ public Enumeration<String> declaredEntities()
4645+ {
4646+ return this.entityInfo.keys();
4647+ }
4648+
4649+ /**
4650+ * Find the type of an entity.
4651+ *
4652+ * @returns An integer constant representing the entity type.
4653+ * @see #ENTITY_UNDECLARED
4654+ * @see #ENTITY_INTERNAL
4655+ * @see #ENTITY_NDATA
4656+ * @see #ENTITY_TEXT
4657+ */
4658+ public int getEntityType(String ename)
4659+ {
4660+ Object entity[] = this.entityInfo.get(ename);
4661+ if (entity == null) {
4662+ return ENTITY_UNDECLARED;
4663+ }
4664+ return ((Integer) entity[0]).intValue();
4665+ }
4666+
4667+ /**
4668+ * Return an external entity's public identifier, if any.
4669+ *
4670+ * @param ename
4671+ * The name of the external entity.
4672+ * @return The entity's system identifier, or null if the entity was not
4673+ * declared, if it is not an external entity, or if no public
4674+ * identifier was provided.
4675+ * @see #getEntityType
4676+ */
4677+ public String getEntityPublicId(String ename)
4678+ {
4679+ Object entity[] = this.entityInfo.get(ename);
4680+ if (entity == null) {
4681+ return null;
4682+ }
4683+ return (String) entity[1];
4684+ }
4685+
4686+ /**
4687+ * Return an external entity's system identifier.
4688+ *
4689+ * @param ename
4690+ * The name of the external entity.
4691+ * @return The entity's system identifier, or null if the entity was not
4692+ * declared, or if it is not an external entity.
4693+ * @see #getEntityType
4694+ */
4695+ public String getEntitySystemId(String ename)
4696+ {
4697+ Object entity[] = this.entityInfo.get(ename);
4698+ if (entity == null) {
4699+ return null;
4700+ }
4701+ return (String) entity[2];
4702+ }
4703+
4704+ /**
4705+ * Return the value of an internal entity.
4706+ *
4707+ * @param ename
4708+ * The name of the internal entity.
4709+ * @return The entity's value, or null if the entity was not declared, or if
4710+ * it is not an internal entity.
4711+ * @see #getEntityType
4712+ */
4713+ public String getEntityValue(String ename)
4714+ {
4715+ Object entity[] = this.entityInfo.get(ename);
4716+ if (entity == null) {
4717+ return null;
4718+ }
4719+ return (String) entity[3];
4720+ }
4721+
4722+ /**
4723+ * Get the notation name associated with an NDATA entity.
4724+ *
4725+ * @param ename
4726+ * The NDATA entity name.
4727+ * @return The associated notation name, or null if the entity was not
4728+ * declared, or if it is not an NDATA entity.
4729+ * @see #getEntityType
4730+ */
4731+ public String getEntityNotationName(String eName)
4732+ {
4733+ Object entity[] = this.entityInfo.get(eName);
4734+ if (entity == null) {
4735+ return null;
4736+ }
4737+ return (String) entity[4];
4738+ }
4739+
4740+ /**
4741+ * Register an entity declaration for later retrieval.
4742+ */
4743+ void setInternalEntity(String eName, String value)
4744+ {
4745+ setEntity(eName, ENTITY_INTERNAL, null, null, value, null);
4746+ }
4747+
4748+ /**
4749+ * Register an external data entity.
4750+ */
4751+ void setExternalDataEntity(String eName, String pubid, String sysid,
4752+ String nName)
4753+ {
4754+ setEntity(eName, ENTITY_NDATA, pubid, sysid, null, nName);
4755+ }
4756+
4757+ /**
4758+ * Register an external text entity.
4759+ */
4760+ void setExternalTextEntity(String eName, String pubid, String sysid)
4761+ {
4762+ setEntity(eName, ENTITY_TEXT, pubid, sysid, null, null);
4763+ }
4764+
4765+ /**
4766+ * Register an entity declaration for later retrieval.
4767+ */
4768+ void setEntity(String eName, int eClass, String pubid, String sysid,
4769+ String value, String nName)
4770+ {
4771+ Object entity[];
4772+
4773+ if (this.entityInfo.get(eName) == null) {
4774+ entity = new Object[5];
4775+ entity[0] = new Integer(eClass);
4776+ entity[1] = pubid;
4777+ entity[2] = sysid;
4778+ entity[3] = value;
4779+ entity[4] = nName;
4780+
4781+ this.entityInfo.put(eName, entity);
4782+ }
4783+ }
4784+
4785+ //
4786+ // Notations.
4787+ //
4788+
4789+ /**
4790+ * Get declared notations.
4791+ *
4792+ * @return An Enumeration of all the notations declared for this XML
4793+ * document. The results will be valid only after the DTD (if any)
4794+ * has been parsed.
4795+ * @see #getNotationPublicId
4796+ * @see #getNotationSystemId
4797+ */
4798+ public Enumeration<String> declaredNotations()
4799+ {
4800+ return this.notationInfo.keys();
4801+ }
4802+
4803+ /**
4804+ * Look up the public identifier for a notation. You will normally use this
4805+ * method to look up a notation that was provided as an attribute value or
4806+ * for an NDATA entity.
4807+ *
4808+ * @param nname
4809+ * The name of the notation.
4810+ * @return A string containing the public identifier, or null if none was
4811+ * provided or if no such notation was declared.
4812+ * @see #getNotationSystemId
4813+ */
4814+ public String getNotationPublicId(String nname)
4815+ {
4816+ Object notation[] = this.notationInfo.get(nname);
4817+ if (notation == null) {
4818+ return null;
4819+ }
4820+ return (String) notation[0];
4821+ }
4822+
4823+ /**
4824+ * Look up the system identifier for a notation. You will normally use this
4825+ * method to look up a notation that was provided as an attribute value or
4826+ * for an NDATA entity.
4827+ *
4828+ * @param nname
4829+ * The name of the notation.
4830+ * @return A string containing the system identifier, or null if no such
4831+ * notation was declared.
4832+ * @see #getNotationPublicId
4833+ */
4834+ public String getNotationSystemId(String nname)
4835+ {
4836+ Object notation[] = this.notationInfo.get(nname);
4837+ if (notation == null) {
4838+ return null;
4839+ }
4840+ return (String) notation[1];
4841+ }
4842+
4843+ /**
4844+ * Register a notation declaration for later retrieval. Format: - public id -
4845+ * system id
4846+ */
4847+ void setNotation(String nname, String pubid, String sysid)
4848+ throws java.lang.Exception
4849+ {
4850+ Object notation[];
4851+
4852+ if (this.notationInfo.get(nname) == null) {
4853+ notation = new Object[2];
4854+ notation[0] = pubid;
4855+ notation[1] = sysid;
4856+ this.notationInfo.put(nname, notation);
4857+ } else {
4858+ error("multiple declarations of notation", nname, null);
4859+ }
4860+ }
4861+
4862+ //
4863+ // Location.
4864+ //
4865+
4866+ /**
4867+ * Return the current line number.
4868+ */
4869+ public int getLineNumber()
4870+ {
4871+ return this.line;
4872+ }
4873+
4874+ /**
4875+ * Return the current column number.
4876+ */
4877+ public int getColumnNumber()
4878+ {
4879+ return this.column;
4880+ }
4881+
4882+ //////////////////////////////////////////////////////////////////////
4883+ // High-level I/O.
4884+ //////////////////////////////////////////////////////////////////////
4885+
4886+ /**
4887+ * Read a single character from the readBuffer.
4888+ * <p>
4889+ * The readDataChunk() method maintains the buffer.
4890+ * <p>
4891+ * If we hit the end of an entity, try to pop the stack and keep going.
4892+ * <p>
4893+ * (This approach doesn't really enforce XML's rules about entity
4894+ * boundaries, but this is not currently a validating parser).
4895+ * <p>
4896+ * This routine also attempts to keep track of the current position in
4897+ * external entities, but it's not entirely accurate.
4898+ *
4899+ * @return The next available input character.
4900+ * @see #unread(char)
4901+ * @see #unread(String)
4902+ * @see #readDataChunk
4903+ * @see #readBuffer
4904+ * @see #line
4905+ * @return The next character from the current input source.
4906+ */
4907+ char readCh() throws java.lang.Exception
4908+ {
4909+ char c;
4910+
4911+ // As long as there's nothing in the
4912+ // read buffer, try reading more data
4913+ // (for an external entity) or popping
4914+ // the entity stack (for either).
4915+ while (this.readBufferPos >= this.readBufferLength) {
4916+ switch (this.sourceType) {
4917+ case INPUT_READER:
4918+ case INPUT_EXTERNAL:
4919+ case INPUT_STREAM:
4920+ readDataChunk();
4921+ while (this.readBufferLength < 1) {
4922+ popInput();
4923+ if (this.readBufferLength < 1) {
4924+ readDataChunk();
4925+ }
4926+ }
4927+ break;
4928+
4929+ default:
4930+ popInput();
4931+ break;
4932+ }
4933+ }
4934+
4935+ c = this.readBuffer[this.readBufferPos++];
4936+
4937+ // This is a particularly nasty bit
4938+ // of code, that checks for a parameter
4939+ // entity reference but peeks ahead to
4940+ // catch the '%' in parameter entity
4941+ // declarations.
4942+ if (c == '%'
4943+ && (this.context == CONTEXT_DTD || this.context == CONTEXT_ENTITYVALUE)) {
4944+ char c2 = readCh();
4945+ unread(c2);
4946+ if (!isWhitespace(c2)) {
4947+ parsePEReference(this.context == CONTEXT_ENTITYVALUE);
4948+ return readCh();
4949+ }
4950+ }
4951+
4952+ if (c == '\n') {
4953+ this.line++;
4954+ this.column = 0;
4955+ } else {
4956+ this.column++;
4957+ }
4958+
4959+ return c;
4960+ }
4961+
4962+ /**
4963+ * Push a single character back onto the current input stream.
4964+ * <p>
4965+ * This method usually pushes the character back onto the readBuffer, while
4966+ * the unread(String) method treats the string as a new internal entity.
4967+ * <p>
4968+ * I don't think that this would ever be called with readBufferPos = 0,
4969+ * because the methods always reads a character before unreading it, but
4970+ * just in case, I've added a boundary condition.
4971+ *
4972+ * @param c
4973+ * The character to push back.
4974+ * @see #readCh
4975+ * @see #unread(String)
4976+ * @see #unread(char[])
4977+ * @see #readBuffer
4978+ */
4979+ void unread(char c) throws java.lang.Exception
4980+ {
4981+ // Normal condition.
4982+ if (c == '\n') {
4983+ this.line--;
4984+ this.column = -1;
4985+ }
4986+ if (this.readBufferPos > 0) {
4987+ this.readBuffer[--this.readBufferPos] = c;
4988+ } else {
4989+ pushString(null, new Character(c).toString());
4990+ }
4991+ }
4992+
4993+ /**
4994+ * Push a char array back onto the current input stream.
4995+ * <p>
4996+ * NOTE: you must <em>never</em> push back characters that you haven't
4997+ * actually read: use pushString() instead.
4998+ *
4999+ * @see #readCh
5000+ * @see #unread(char)
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches