foray-commit Mailing List for FOray (Page 31)
Modular XSL-FO Implementation for Java.
Status: Alpha
Brought to you by:
victormote
You can subscribe to this list here.
| 2006 |
Jan
|
Feb
|
Mar
(139) |
Apr
(98) |
May
(250) |
Jun
(394) |
Jul
(84) |
Aug
(13) |
Sep
(420) |
Oct
(186) |
Nov
(1) |
Dec
(3) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2007 |
Jan
(108) |
Feb
(202) |
Mar
(291) |
Apr
(247) |
May
(374) |
Jun
(227) |
Jul
(231) |
Aug
(60) |
Sep
(31) |
Oct
(45) |
Nov
(18) |
Dec
|
| 2008 |
Jan
(38) |
Feb
(71) |
Mar
(142) |
Apr
|
May
(59) |
Jun
(6) |
Jul
(10) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2009 |
Jan
(12) |
Feb
(4) |
Mar
(88) |
Apr
(121) |
May
(17) |
Jun
(30) |
Jul
|
Aug
(5) |
Sep
|
Oct
(1) |
Nov
|
Dec
|
| 2010 |
Jan
(11) |
Feb
(76) |
Mar
(11) |
Apr
|
May
(11) |
Jun
|
Jul
|
Aug
(44) |
Sep
(14) |
Oct
(7) |
Nov
|
Dec
|
| 2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(9) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(10) |
Nov
|
Dec
|
| 2012 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(3) |
Jul
(4) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2016 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(168) |
| 2017 |
Jan
(77) |
Feb
(11) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2018 |
Jan
|
Feb
|
Mar
(1) |
Apr
(6) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2019 |
Jan
|
Feb
(88) |
Mar
(118) |
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2020 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(6) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(141) |
| 2021 |
Jan
(170) |
Feb
(20) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
(62) |
Nov
(189) |
Dec
(162) |
| 2022 |
Jan
(201) |
Feb
(118) |
Mar
(8) |
Apr
|
May
(2) |
Jun
(47) |
Jul
(19) |
Aug
(14) |
Sep
(3) |
Oct
|
Nov
(28) |
Dec
(235) |
| 2023 |
Jan
(112) |
Feb
(23) |
Mar
(2) |
Apr
(2) |
May
|
Jun
(1) |
Jul
|
Aug
(70) |
Sep
(92) |
Oct
(20) |
Nov
(1) |
Dec
(1) |
| 2024 |
Jan
|
Feb
|
Mar
(1) |
Apr
(1) |
May
(14) |
Jun
(11) |
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2025 |
Jan
(10) |
Feb
(29) |
Mar
|
Apr
(162) |
May
(245) |
Jun
(83) |
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
|
|
From: <vic...@us...> - 2023-02-05 14:02:48
|
Revision: 13125
http://sourceforge.net/p/foray/code/13125
Author: victormote
Date: 2023-02-05 14:02:46 +0000 (Sun, 05 Feb 2023)
Log Message:
-----------
Add interface for StAX cursor readers.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxEventIteratorReader.java
Added Paths:
-----------
trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxCursorReader.java
Added: trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxCursorReader.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxCursorReader.java (rev 0)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxCursorReader.java 2023-02-05 14:02:46 UTC (rev 13125)
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2023 The FOray Project.
+ * http://www.foray.org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This work is in part derived from the following work(s), used with the
+ * permission of the licensor:
+ * Apache FOP, licensed by the Apache Software Foundation
+ *
+ */
+
+/*
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ * $LastChangedBy$
+ */
+
+package org.foray.xml;
+
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+/**
+ * Boilerplate code for XML parsers using the StAX iterator API.
+ */
+public interface StaxCursorReader {
+
+ /**
+ * Iterates the events parsed from an XML stream reader.
+ * @param reader The XML stream reader moving the cursor over the document.
+ * @throws XMLStreamException For errors during parsing.
+ */
+ default void iterate(final XMLStreamReader reader) throws XMLStreamException {
+ while (reader.hasNext()) {
+ processEvent(reader);
+ reader.next();
+ }
+ }
+
+ /**
+ * Process the event to which the cursor currently points.
+ * @param reader The reader.
+ */
+ default void processEvent(final XMLStreamReader reader) {
+ switch (reader.getEventType()) {
+ case XMLStreamConstants.START_ELEMENT: {
+ processStartElement(reader);
+ break;
+ }
+ case XMLStreamConstants.END_ELEMENT: {
+ processEndElement(reader);
+ break;
+ }
+ case XMLStreamConstants.PROCESSING_INSTRUCTION: {
+ processProcessingInstruction(reader);
+ break;
+ }
+ case XMLStreamConstants.CHARACTERS:
+ processCharacters(reader);
+ break;
+ case XMLStreamConstants.COMMENT:
+ processComment(reader);
+ break;
+ case XMLStreamConstants.SPACE: {
+ processSpace(reader);
+ break;
+ }
+ case XMLStreamConstants.START_DOCUMENT: {
+ processStartDocument(reader);
+ break;
+ }
+ case XMLStreamConstants.END_DOCUMENT: {
+ processEndDocument(reader);
+ break;
+ }
+ case XMLStreamConstants.ENTITY_REFERENCE: {
+ processEntityReference(reader);
+ break;
+ }
+ case XMLStreamConstants.ATTRIBUTE: {
+ processAttribute(reader);
+ break;
+ }
+ case XMLStreamConstants.DTD: {
+ processDtd(reader);
+ break;
+ }
+ case XMLStreamConstants.CDATA: {
+ processCdata(reader);
+ break;
+ }
+ case XMLStreamConstants.NAMESPACE: {
+ processNamespace(reader);
+ break;
+ }
+ case XMLStreamConstants.NOTATION_DECLARATION: {
+ processNotationDeclaration(reader);
+ break;
+ }
+ case XMLStreamConstants.ENTITY_DECLARATION: {
+ processEntityDeclaration(reader);
+ break;
+ }
+ }
+
+ }
+
+ /**
+ * Process a "start element" event.
+ * @param reader The reader.
+ */
+ default void processStartElement(final XMLStreamReader reader) {
+ }
+
+ /**
+ * Process an "end element" event.
+ * @param reader The reader.
+ */
+ default void processEndElement(final XMLStreamReader reader) {
+ }
+
+ /**
+ * Process an "processing instruction" event.
+ * @param reader The reader.
+ */
+ default void processProcessingInstruction(final XMLStreamReader reader) {
+ }
+
+ /**
+ * Process a "characters" event.
+ * @param reader The reader.
+ */
+ default void processCharacters(final XMLStreamReader reader) {
+ }
+
+ /**
+ * Process a "comment" event.
+ * @param reader The reader.
+ */
+ default void processComment(final XMLStreamReader reader) {
+ }
+
+ /**
+ * Process a "space" event (ignorable whitespace).
+ * @param reader The reader.
+ */
+ default void processSpace(final XMLStreamReader reader) {
+ }
+
+ /**
+ * Process a "start document" event.
+ * @param reader The reader.
+ */
+ default void processStartDocument(final XMLStreamReader reader) {
+ }
+
+ /**
+ * Process an "end document" event.
+ * @param reader The reader.
+ */
+ default void processEndDocument(final XMLStreamReader reader) {
+ }
+
+ /**
+ * Process an "entity reference" event.
+ * @param reader The reader.
+ */
+ default void processEntityReference(final XMLStreamReader reader) {
+ }
+
+ /**
+ * Process an "attribute" event.
+ * @param reader The reader.
+ */
+ default void processAttribute(final XMLStreamReader reader) {
+ }
+
+ /**
+ * Process a "DTD" event.
+ * @param reader The reader.
+ */
+ default void processDtd(final XMLStreamReader reader) {
+ }
+
+ /**
+ * Process a "CDATA" event.
+ * @param reader The reader.
+ */
+ default void processCdata(final XMLStreamReader reader) {
+ }
+
+ /**
+ * Process a "namespace" event.
+ * @param reader The reader.
+ */
+ default void processNamespace(final XMLStreamReader reader) {
+ }
+
+ /**
+ * Process a "notation declaration" event.
+ * @param reader The reader.
+ */
+ default void processNotationDeclaration(final XMLStreamReader reader) {
+ }
+
+ /**
+ * Process a "entity declaration" event.
+ * @param reader The reader.
+ */
+ default void processEntityDeclaration(final XMLStreamReader reader) {
+ }
+
+
+}
Property changes on: trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxCursorReader.java
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Rev
\ No newline at end of property
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxEventIteratorReader.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxEventIteratorReader.java 2023-02-05 13:48:29 UTC (rev 13124)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxEventIteratorReader.java 2023-02-05 14:02:46 UTC (rev 13125)
@@ -174,7 +174,6 @@
* @param event The event being processed.
*/
default void processSpace(final XMLEvent event) {
- /* Ignorable whitespace. Just ignore it. */
}
/**
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-02-05 13:48:32
|
Revision: 13124
http://sourceforge.net/p/foray/code/13124
Author: victormote
Date: 2023-02-05 13:48:29 +0000 (Sun, 05 Feb 2023)
Log Message:
-----------
Rename class for clarity.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyOutput.java
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPull.java
Added Paths:
-----------
trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxEventIteratorReader.java
Removed Paths:
-------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxIterator.java
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyOutput.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyOutput.java 2023-02-05 12:55:56 UTC (rev 13123)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyOutput.java 2023-02-05 13:48:29 UTC (rev 13124)
@@ -501,4 +501,11 @@
}
}
+ /**
+ * Writes the end-of-line character(s) to the output.
+ */
+ void writeLineTerminator() {
+ write(this.config.getLineTerminator());
+ }
+
}
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPull.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPull.java 2023-02-05 12:55:56 UTC (rev 13123)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPull.java 2023-02-05 13:48:29 UTC (rev 13124)
@@ -58,7 +58,7 @@
* XML pretty-printer using pull-parsing.
* Specifically, this class uses the event iterator model of StAX.
*/
-public class ForayPrettyPull implements StaxIterator {
+public class ForayPrettyPull implements StaxEventIteratorReader {
/** The configuration for this pretty-printer. */
private ForayPrettyConfig config;
Copied: trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxEventIteratorReader.java (from rev 13120, trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxIterator.java)
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxEventIteratorReader.java (rev 0)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxEventIteratorReader.java 2023-02-05 13:48:29 UTC (rev 13124)
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2023 The FOray Project.
+ * http://www.foray.org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This work is in part derived from the following work(s), used with the
+ * permission of the licensor:
+ * Apache FOP, licensed by the Apache Software Foundation
+ *
+ */
+
+/*
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ * $LastChangedBy$
+ */
+
+package org.foray.xml;
+
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.Characters;
+import javax.xml.stream.events.Comment;
+import javax.xml.stream.events.DTD;
+import javax.xml.stream.events.EndDocument;
+import javax.xml.stream.events.EndElement;
+import javax.xml.stream.events.EntityDeclaration;
+import javax.xml.stream.events.EntityReference;
+import javax.xml.stream.events.Namespace;
+import javax.xml.stream.events.NotationDeclaration;
+import javax.xml.stream.events.ProcessingInstruction;
+import javax.xml.stream.events.StartDocument;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+
+/**
+ * Boilerplate code for XML parsers using the StAX iterator API.
+ */
+public interface StaxEventIteratorReader {
+
+ /**
+ * Iterates the events parsed from an XML event reader.
+ * @param reader The XML event reader providing the events for the document being parsed.
+ * @throws XMLStreamException For errors during parsing.
+ */
+ default void iterate(final XMLEventReader reader) throws XMLStreamException {
+ while (reader.hasNext()) {
+ final XMLEvent event = reader.nextEvent();
+ switch (event.getEventType()) {
+ case XMLEvent.START_ELEMENT: {
+ final StartElement startElement = event.asStartElement();
+ processStartElement(startElement);
+ break;
+ }
+ case XMLEvent.END_ELEMENT: {
+ final EndElement endElement = event.asEndElement();
+ processEndElement(endElement);
+ break;
+ }
+ case XMLEvent.PROCESSING_INSTRUCTION: {
+ final ProcessingInstruction pi = (ProcessingInstruction) event;
+ processProcessingInstruction(pi);
+ break;
+ }
+ case XMLEvent.CHARACTERS:
+ final Characters characters = event.asCharacters();
+ processCharacters(characters);
+ break;
+ case XMLEvent.COMMENT:
+ final Comment comment = (Comment) event;
+ processComment(comment);
+ break;
+ case XMLEvent.SPACE: {
+ processSpace(event);
+ break;
+ }
+ case XMLEvent.START_DOCUMENT: {
+ final StartDocument startDocument = (StartDocument) event;
+ processStartDocument(startDocument);
+ break;
+ }
+ case XMLEvent.END_DOCUMENT: {
+ final EndDocument endDocument = (EndDocument) event;
+ processEndDocument(endDocument);
+ break;
+ }
+ case XMLEvent.ENTITY_REFERENCE: {
+ final EntityReference entityReference = (EntityReference) event;
+ processEntityReference(entityReference);
+ break;
+ }
+ case XMLEvent.ATTRIBUTE: {
+ final Attribute attribute = (Attribute) event;
+ processAttribute(attribute);
+ break;
+ }
+ case XMLEvent.DTD: {
+ final DTD dtd = (DTD) event;
+ processDtd(dtd);
+ break;
+ }
+ case XMLEvent.CDATA: {
+ processCdata(event);
+ break;
+ }
+ case XMLEvent.NAMESPACE: {
+ final Namespace namespace = (Namespace) event;
+ processNamespace(namespace);
+ break;
+ }
+ case XMLEvent.NOTATION_DECLARATION: {
+ final NotationDeclaration notationDeclaration = (NotationDeclaration) event;
+ processNotationDeclaration(notationDeclaration);
+ break;
+ }
+ case XMLEvent.ENTITY_DECLARATION: {
+ final EntityDeclaration entityDeclaration = (EntityDeclaration) event;
+ processEntityDeclaration(entityDeclaration);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Process a "start element" event.
+ * @param startElement The event being processed.
+ */
+ default void processStartElement(StartElement startElement) {
+ }
+
+ /**
+ * Process an "end element" event.
+ * @param endElement The event being processed.
+ */
+ default void processEndElement(final EndElement endElement) {
+ }
+
+ /**
+ * Process an "processing instruction" event.
+ * @param pi The event being processed.
+ */
+ default void processProcessingInstruction(final ProcessingInstruction pi) {
+ }
+
+ /**
+ * Process a "characters" event.
+ * @param characters The event being processed.
+ */
+ default void processCharacters(final Characters characters) {
+ }
+
+ /**
+ * Process a "comment" event.
+ * @param comment The event being processed.
+ */
+ default void processComment(final Comment comment) {
+ }
+
+ /**
+ * Process a "space" event (ignorable whitespace).
+ * @param event The event being processed.
+ */
+ default void processSpace(final XMLEvent event) {
+ /* Ignorable whitespace. Just ignore it. */
+ }
+
+ /**
+ * Process a "start document" event.
+ * @param startDocument The event being processed.
+ */
+ default void processStartDocument(final StartDocument startDocument) {
+ }
+
+ /**
+ * Process an "end document" event.
+ * @param endDocument The event being processed.
+ */
+ default void processEndDocument(final EndDocument endDocument) {
+ }
+
+ /**
+ * Process an "entity reference" event.
+ * @param entityReference The event being processed.
+ */
+ default void processEntityReference(final EntityReference entityReference) {
+ }
+
+ /**
+ * Process an "attribute" event.
+ * @param attribute The event being processed.
+ */
+ default void processAttribute(final Attribute attribute) {
+ }
+
+ /**
+ * Process a "DTD" event.
+ * @param dtd The event being processed.
+ */
+ default void processDtd(final DTD dtd) {
+ }
+
+ /**
+ * Process a "CDATA" event.
+ * @param event The event being processed.
+ */
+ default void processCdata(final XMLEvent event) {
+ }
+
+ /**
+ * Process a "namespace" event.
+ * @param namespace The event being processed.
+ */
+ default void processNamespace(final Namespace namespace) {
+ }
+
+ /**
+ * Process a "notation declaration" event.
+ * @param notationDeclaration The event being processed.
+ */
+ default void processNotationDeclaration(final NotationDeclaration notationDeclaration) {
+ }
+
+ /**
+ * Process a "entity declaration" event.
+ * @param entityDeclaration The event being processed.
+ */
+ default void processEntityDeclaration(final EntityDeclaration entityDeclaration) {
+ }
+
+
+}
Deleted: trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxIterator.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxIterator.java 2023-02-05 12:55:56 UTC (rev 13123)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxIterator.java 2023-02-05 13:48:29 UTC (rev 13124)
@@ -1,244 +0,0 @@
-/*
- * Copyright 2023 The FOray Project.
- * http://www.foray.org
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * This work is in part derived from the following work(s), used with the
- * permission of the licensor:
- * Apache FOP, licensed by the Apache Software Foundation
- *
- */
-
-/*
- * $LastChangedRevision$
- * $LastChangedDate$
- * $LastChangedBy$
- */
-
-package org.foray.xml;
-
-import javax.xml.stream.XMLEventReader;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.events.Attribute;
-import javax.xml.stream.events.Characters;
-import javax.xml.stream.events.Comment;
-import javax.xml.stream.events.DTD;
-import javax.xml.stream.events.EndDocument;
-import javax.xml.stream.events.EndElement;
-import javax.xml.stream.events.EntityDeclaration;
-import javax.xml.stream.events.EntityReference;
-import javax.xml.stream.events.Namespace;
-import javax.xml.stream.events.NotationDeclaration;
-import javax.xml.stream.events.ProcessingInstruction;
-import javax.xml.stream.events.StartDocument;
-import javax.xml.stream.events.StartElement;
-import javax.xml.stream.events.XMLEvent;
-
-/**
- * Boilerplate code for XML parsers using the StAX iterator API.
- */
-public interface StaxIterator {
-
- /**
- * Iterates the events parsed from an XML event reader.
- * @param reader The XML event reader providing the events for the document being parsed.
- * @throws XMLStreamException For errors during parsing.
- */
- default void iterate(final XMLEventReader reader) throws XMLStreamException {
- while (reader.hasNext()) {
- final XMLEvent event = reader.nextEvent();
- switch (event.getEventType()) {
- case XMLEvent.START_ELEMENT: {
- final StartElement startElement = event.asStartElement();
- processStartElement(startElement);
- break;
- }
- case XMLEvent.END_ELEMENT: {
- final EndElement endElement = event.asEndElement();
- processEndElement(endElement);
- break;
- }
- case XMLEvent.PROCESSING_INSTRUCTION: {
- final ProcessingInstruction pi = (ProcessingInstruction) event;
- processProcessingInstruction(pi);
- break;
- }
- case XMLEvent.CHARACTERS:
- final Characters characters = event.asCharacters();
- processCharacters(characters);
- break;
- case XMLEvent.COMMENT:
- final Comment comment = (Comment) event;
- processComment(comment);
- break;
- case XMLEvent.SPACE: {
- processSpace(event);
- break;
- }
- case XMLEvent.START_DOCUMENT: {
- final StartDocument startDocument = (StartDocument) event;
- processStartDocument(startDocument);
- break;
- }
- case XMLEvent.END_DOCUMENT: {
- final EndDocument endDocument = (EndDocument) event;
- processEndDocument(endDocument);
- break;
- }
- case XMLEvent.ENTITY_REFERENCE: {
- final EntityReference entityReference = (EntityReference) event;
- processEntityReference(entityReference);
- break;
- }
- case XMLEvent.ATTRIBUTE: {
- final Attribute attribute = (Attribute) event;
- processAttribute(attribute);
- break;
- }
- case XMLEvent.DTD: {
- final DTD dtd = (DTD) event;
- processDtd(dtd);
- break;
- }
- case XMLEvent.CDATA: {
- processCdata(event);
- break;
- }
- case XMLEvent.NAMESPACE: {
- final Namespace namespace = (Namespace) event;
- processNamespace(namespace);
- break;
- }
- case XMLEvent.NOTATION_DECLARATION: {
- final NotationDeclaration notationDeclaration = (NotationDeclaration) event;
- processNotationDeclaration(notationDeclaration);
- break;
- }
- case XMLEvent.ENTITY_DECLARATION: {
- final EntityDeclaration entityDeclaration = (EntityDeclaration) event;
- processEntityDeclaration(entityDeclaration);
- break;
- }
- }
- }
- }
-
- /**
- * Process a "start element" event.
- * @param startElement The event being processed.
- */
- default void processStartElement(StartElement startElement) {
- }
-
- /**
- * Process an "end element" event.
- * @param endElement The event being processed.
- */
- default void processEndElement(final EndElement endElement) {
- }
-
- /**
- * Process an "processing instruction" event.
- * @param pi The event being processed.
- */
- default void processProcessingInstruction(final ProcessingInstruction pi) {
- }
-
- /**
- * Process a "characters" event.
- * @param characters The event being processed.
- */
- default void processCharacters(final Characters characters) {
- }
-
- /**
- * Process a "comment" event.
- * @param comment The event being processed.
- */
- default void processComment(final Comment comment) {
- }
-
- /**
- * Process a "space" event (ignorable whitespace).
- * @param event The event being processed.
- */
- default void processSpace(final XMLEvent event) {
- /* Ignorable whitespace. Just ignore it. */
- }
-
- /**
- * Process a "start document" event.
- * @param startDocument The event being processed.
- */
- default void processStartDocument(final StartDocument startDocument) {
- }
-
- /**
- * Process an "end document" event.
- * @param endDocument The event being processed.
- */
- default void processEndDocument(final EndDocument endDocument) {
- }
-
- /**
- * Process an "entity reference" event.
- * @param entityReference The event being processed.
- */
- default void processEntityReference(final EntityReference entityReference) {
- }
-
- /**
- * Process an "attribute" event.
- * @param attribute The event being processed.
- */
- default void processAttribute(final Attribute attribute) {
- }
-
- /**
- * Process a "DTD" event.
- * @param dtd The event being processed.
- */
- default void processDtd(final DTD dtd) {
- }
-
- /**
- * Process a "CDATA" event.
- * @param event The event being processed.
- */
- default void processCdata(final XMLEvent event) {
- }
-
- /**
- * Process a "namespace" event.
- * @param namespace The event being processed.
- */
- default void processNamespace(final Namespace namespace) {
- }
-
- /**
- * Process a "notation declaration" event.
- * @param notationDeclaration The event being processed.
- */
- default void processNotationDeclaration(final NotationDeclaration notationDeclaration) {
- }
-
- /**
- * Process a "entity declaration" event.
- * @param entityDeclaration The event being processed.
- */
- default void processEntityDeclaration(final EntityDeclaration entityDeclaration) {
- }
-
-
-}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-02-05 12:55:59
|
Revision: 13123
http://sourceforge.net/p/foray/code/13123
Author: victormote
Date: 2023-02-05 12:55:56 +0000 (Sun, 05 Feb 2023)
Log Message:
-----------
Store QName instead of just the name.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/DtdElement.java
trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/ElementStack.java
trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XmlModelElement.java
trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XsdElement.java
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/DtdElement.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/DtdElement.java 2023-02-04 23:21:34 UTC (rev 13122)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/DtdElement.java 2023-02-05 12:55:56 UTC (rev 13123)
@@ -30,13 +30,15 @@
import org.foray.xml.model.XmlModelElement;
+import javax.xml.namespace.QName;
+
/**
* An element declaration in an SGML/XML Document Type Definition (DTD).
*/
public class DtdElement implements XmlModelElement {
- /** The name of this element. */
- private String elementName;
+ /** The QName for this element. */
+ private QName qname;
/** Indicates whether this element contains PCDATA. */
private boolean hasPCDATA = false;
@@ -53,7 +55,7 @@
* @param contentModel The unparsed content model for this element.
*/
public DtdElement(final String elementName, final String contentModel) {
- this.elementName = elementName;
+ this.qname = new QName(null, elementName);
parseContentModel(contentModel);
}
@@ -67,12 +69,10 @@
if (contentModel.indexOf("#PCDATA") > -1) {
this.hasPCDATA = true;
}
- final String[] contentTokens = DtdTokenizer.tokenizeElementContent(
- contentModel);
+ final String[] contentTokens = DtdTokenizer.tokenizeElementContent(contentModel);
this.isEmpty = DtdTokenizer.isElementContentEmpty(contentTokens);
this.hasPCDATA = DtdTokenizer.hasPCDATA(contentTokens);
- this.hasElementChildren = DtdTokenizer.hasElementChildren(
- contentTokens);
+ this.hasElementChildren = DtdTokenizer.hasElementChildren(contentTokens);
}
/**
@@ -80,7 +80,7 @@
* @return The element name.
*/
public String getName() {
- return this.elementName;
+ return this.qname.getLocalPart();
}
@Override
@@ -104,4 +104,9 @@
return this.hasElementChildren;
}
+ @Override
+ public QName getQname() {
+ return this.qname;
+ }
+
}
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/ElementStack.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/ElementStack.java 2023-02-04 23:21:34 UTC (rev 13122)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/ElementStack.java 2023-02-05 12:55:56 UTC (rev 13123)
@@ -84,7 +84,7 @@
* To get the top element, set to 0. To get the next element down, set to 1, etc.
* @return The nth item down the stack, where n is indexFromTop.
*/
- private XmlModelElement peek(final int indexFromTop) {
+ public XmlModelElement peek(final int indexFromTop) {
if (this.stack.size() <= indexFromTop) {
return null;
}
@@ -93,6 +93,17 @@
}
/**
+ * Returns the element at the bottom of the stack.
+ * @return The element at the bottom of the stack, or null if the stack is empty.
+ */
+ public XmlModelElement getBottom() {
+ if (this.stack.size() < 1) {
+ return null;
+ }
+ return this.stack.get(0);
+ }
+
+ /**
* Return the number of elements on the stack.
* @return The number of elements on the stack.
*/
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XmlModelElement.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XmlModelElement.java 2023-02-04 23:21:34 UTC (rev 13122)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XmlModelElement.java 2023-02-05 12:55:56 UTC (rev 13123)
@@ -28,6 +28,8 @@
package org.foray.xml.model;
+import javax.xml.namespace.QName;
+
/**
* A generic XML Element type, agnostic of which model (DTD or XSD) was used to define it.
*/
@@ -39,4 +41,10 @@
*/
boolean hasPCDATA();
+ /**
+ * Returns the QName for this element.
+ * @return THe QName for this element.
+ */
+ QName getQname();
+
}
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XsdElement.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XsdElement.java 2023-02-04 23:21:34 UTC (rev 13122)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XsdElement.java 2023-02-05 12:55:56 UTC (rev 13123)
@@ -30,6 +30,8 @@
import org.apache.ws.commons.schema.XmlSchemaElement;
+import javax.xml.namespace.QName;
+
/**
* An element declaration in an XML Schema (XSD).
* Wraps an instance of {@link XmlSchemaElement} .
@@ -60,4 +62,9 @@
return element.getSchemaType().isMixed();
}
+ @Override
+ public QName getQname() {
+ return this.element.getSchemaTypeName();
+ }
+
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-02-04 23:21:37
|
Revision: 13122
http://sourceforge.net/p/foray/code/13122
Author: victormote
Date: 2023-02-04 23:21:34 +0000 (Sat, 04 Feb 2023)
Log Message:
-----------
Replace custom primitive code for clearing a StringBuilder with standard code.
Modified Paths:
--------------
trunk/foray/foray-fotree/src/main/java/org/foray/fotree/FoTreeParser4a.java
trunk/foray/foray-linebreak/src/test/java/org/foray/linebreak/util/DumpLayout.java
trunk/foray/foray-orthography/src/main/java/org/foray/orthography/util/DictionaryParser.java
trunk/foray/foray-primitive/src/main/java/org/foray/primitive/StringUtils.java
trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java
Modified: trunk/foray/foray-fotree/src/main/java/org/foray/fotree/FoTreeParser4a.java
===================================================================
--- trunk/foray/foray-fotree/src/main/java/org/foray/fotree/FoTreeParser4a.java 2023-02-04 23:03:58 UTC (rev 13121)
+++ trunk/foray/foray-fotree/src/main/java/org/foray/fotree/FoTreeParser4a.java 2023-02-04 23:21:34 UTC (rev 13122)
@@ -36,7 +36,6 @@
import org.foray.fotree.fo.obj.PageSequence4a;
import org.foray.fotree.fo.obj.Root4a;
import org.foray.fotree.foreign.ForeignNamespaceHandler;
-import org.foray.primitive.StringUtils;
import org.foray.xml.SaxParser;
import org.axsl.constants.XmlConstants;
@@ -138,7 +137,7 @@
public void reset() {
this.currentFObj = null;
this.foTreeListeners.clear();
- StringUtils.clear(this.textBuffer);
+ this.textBuffer.setLength(0);
this.foTree = new FoTree4a(this.server);
foTree.setOrthographyServer(this.server.getOrthographyServer());
this.resourceSearchPath = this.server.getResourceSearchPath() == null ?
Modified: trunk/foray/foray-linebreak/src/test/java/org/foray/linebreak/util/DumpLayout.java
===================================================================
--- trunk/foray/foray-linebreak/src/test/java/org/foray/linebreak/util/DumpLayout.java 2023-02-04 23:03:58 UTC (rev 13121)
+++ trunk/foray/foray-linebreak/src/test/java/org/foray/linebreak/util/DumpLayout.java 2023-02-04 23:21:34 UTC (rev 13122)
@@ -29,7 +29,6 @@
package org.foray.linebreak.util;
import org.foray.linebreak.FirstFitLbTests;
-import org.foray.primitive.StringUtils;
import org.foray.primitive.sequence.IntArray;
import org.axsl.kp.KpBranch;
@@ -61,7 +60,7 @@
final int nextBreakLeaf = layout[nextBreakIndex];
if (leafIndex == nextBreakLeaf) {
this.output.println(builder.toString());
- StringUtils.clear(builder);
+ builder.setLength(0);
}
}
final KpLeaf leaf = branch.kpLeafAt(leafIndex);
Modified: trunk/foray/foray-orthography/src/main/java/org/foray/orthography/util/DictionaryParser.java
===================================================================
--- trunk/foray/foray-orthography/src/main/java/org/foray/orthography/util/DictionaryParser.java 2023-02-04 23:03:58 UTC (rev 13121)
+++ trunk/foray/foray-orthography/src/main/java/org/foray/orthography/util/DictionaryParser.java 2023-02-04 23:21:34 UTC (rev 13122)
@@ -394,7 +394,7 @@
}
case "t": {
final String inputLine = getAndClearText();
- StringUtils.clear(this.builder);
+ this.builder.setLength(0);
this.segmentList.clear();
int inputLineIndex = 0;
Modified: trunk/foray/foray-primitive/src/main/java/org/foray/primitive/StringUtils.java
===================================================================
--- trunk/foray/foray-primitive/src/main/java/org/foray/primitive/StringUtils.java 2023-02-04 23:03:58 UTC (rev 13121)
+++ trunk/foray/foray-primitive/src/main/java/org/foray/primitive/StringUtils.java 2023-02-04 23:21:34 UTC (rev 13122)
@@ -426,17 +426,6 @@
}
/**
- * Removes all content from a given StringBuilder instance.
- * @param builder The StringBuilder to be cleared.
- */
- public static void clear(final StringBuilder builder) {
- if (builder == null) {
- return;
- }
- builder.delete(0, builder.length());
- }
-
- /**
* Converts an array of bytes to String of its hexadecimal equivalent.
* @param value The bytes to be converted.
* @return A String containing the hex equivalent of the byte input, that
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java 2023-02-04 23:03:58 UTC (rev 13121)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java 2023-02-04 23:21:34 UTC (rev 13122)
@@ -435,7 +435,7 @@
*/
public String getAndClearText() {
final String content = this.textAccumulator.toString();
- StringUtils.clear(this.textAccumulator);
+ this.textAccumulator.setLength(0);
return content;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-02-04 23:04:00
|
Revision: 13121
http://sourceforge.net/p/foray/code/13121
Author: victormote
Date: 2023-02-04 23:03:58 +0000 (Sat, 04 Feb 2023)
Log Message:
-----------
Use the superclass StringBuilder.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java 2023-02-04 18:52:07 UTC (rev 13120)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java 2023-02-04 23:03:58 UTC (rev 13121)
@@ -81,9 +81,6 @@
/** A output for this pretty-printer. */
private ForayPrettyOutput prettyOutput;
- /** A reusable buffer. */
- private StringBuilder charBuffer = new StringBuilder();
-
/** The name of the root element of this document. */
private String rootElement;
@@ -350,7 +347,7 @@
* expanded version. */
return;
}
- this.charBuffer.append(buffer, offset, length);
+ getTextAccumulator().append(buffer, offset, length);
}
/**
@@ -357,20 +354,20 @@
* Pushes any character in the buffer into the queue to be written.
*/
private void flushCharacters() {
- if (this.charBuffer.length() < 1) {
+ if (getTextAccumulator().length() < 1) {
return;
}
ensureTopElementWritten(false);
if (this.inCdata) {
- this.prettyOutput.writeRawPCDATA(this.charBuffer.toString());
+ this.prettyOutput.writeRawPCDATA(getTextAccumulator().toString());
} else if (this.config.isBreakPCDATA()) {
/* Note: SAX input has linefeeds normalized to \n. */
- XmlUtils.normalizeWhitespace(this.charBuffer);
- this.prettyOutput.add(this.charBuffer.toString());
+ XmlUtils.normalizeWhitespace(getTextAccumulator());
+ this.prettyOutput.add(getTextAccumulator().toString());
} else {
- this.prettyOutput.writeRawPCDATA(this.charBuffer.toString());
+ this.prettyOutput.writeRawPCDATA(getTextAccumulator().toString());
}
- this.charBuffer.setLength(0);
+ getAndClearText();
}
@Override
@@ -457,10 +454,10 @@
/* General entity references have their "&" prefix stripped off, so we must add it back. Parameters entity
* references have their "%" prefix left intact. */
if (name.charAt(0) != '%') {
- this.charBuffer.append("&");
+ appendText("&");
}
- this.charBuffer.append(name);
- this.charBuffer.append(";");
+ appendText(name);
+ appendText(";");
this.inEntityReference = true;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-02-04 18:52:09
|
Revision: 13120
http://sourceforge.net/p/foray/code/13120
Author: victormote
Date: 2023-02-04 18:52:07 +0000 (Sat, 04 Feb 2023)
Log Message:
-----------
Rough-in the beginning of a pull-parser pretty-print solution.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyOutput.java
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java
Added Paths:
-----------
trunk/foray/foray-00-master/ide/eclipse/launch-configurations/xml-ForayPrettyPull.launch
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPull.java
trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxIterator.java
Added: trunk/foray/foray-00-master/ide/eclipse/launch-configurations/xml-ForayPrettyPull.launch
===================================================================
--- trunk/foray/foray-00-master/ide/eclipse/launch-configurations/xml-ForayPrettyPull.launch (rev 0)
+++ trunk/foray/foray-00-master/ide/eclipse/launch-configurations/xml-ForayPrettyPull.launch 2023-02-04 18:52:07 UTC (rev 13120)
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
+ <booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
+ <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+ <listEntry value="/foray-xml/src/main/java/org/foray/xml/ForayPrettyPull.java"/>
+ </listAttribute>
+ <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+ <listEntry value="1"/>
+ </listAttribute>
+ <booleanAttribute key="org.eclipse.jdt.launching.ATTR_EXCLUDE_TEST_CODE" value="true"/>
+ <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_CLASSPATH_ONLY_JAR" value="false"/>
+ <listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
+ <listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/" javaProject="foray-xml" path="1" type="4"/> "/>
+ <listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry id="org.eclipse.jdt.launching.classpathentry.defaultClasspath"> <memento exportedEntriesOnly="false" project="foray-xml"/> </runtimeClasspathEntry> "/>
+ <listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.USER_LIBRARY/logback" path="3" type="4"/> "/>
+ </listAttribute>
+ <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
+ <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.foray.xml.ForayPrettyPull"/>
+ <stringAttribute key="org.eclipse.jdt.launching.MODULE_NAME" value="foray-xml"/>
+ <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="--input ${foray-test-input-dir}/pretty-print-input.xml --output ${foray-test-output-dir}/pretty-print-output.xml --catalog ${foray-catalog-file}"/>
+ <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="foray-xml"/>
+</launchConfiguration>
Property changes on: trunk/foray/foray-00-master/ide/eclipse/launch-configurations/xml-ForayPrettyPull.launch
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Rev
\ No newline at end of property
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyOutput.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyOutput.java 2023-02-04 16:26:50 UTC (rev 13119)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyOutput.java 2023-02-04 18:52:07 UTC (rev 13120)
@@ -424,6 +424,14 @@
}
/**
+ * Returns the configuration.
+ * @return The configuration.
+ */
+ public ForayPrettyConfig getConfig() {
+ return this.config;
+ }
+
+ /**
* Closes the output stream.
* @throws IOException For errors closing output stream.
*/
Added: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPull.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPull.java (rev 0)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPull.java 2023-02-04 18:52:07 UTC (rev 13120)
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2023 The FOray Project.
+ * http://www.foray.org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This work is in part derived from the following work(s), used with the
+ * permission of the licensor:
+ * Apache FOP, licensed by the Apache Software Foundation
+ *
+ */
+
+/*
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ * $LastChangedBy$
+ */
+
+package org.foray.xml;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.InputSource;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.xml.XMLConstants;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.StartElement;
+
+/**
+ * XML pretty-printer using pull-parsing.
+ * Specifically, this class uses the event iterator model of StAX.
+ */
+public class ForayPrettyPull implements StaxIterator {
+
+ /** The configuration for this pretty-printer. */
+ private ForayPrettyConfig config;
+
+ /** A output for this pretty-printer. */
+ private ForayPrettyOutput prettyOutput;
+
+ /** The StAX event iterator. */
+ private XMLEventReader reader;
+
+// /** The logger. */
+// private Logger logger = LoggerFactory.getLogger(ForayPrettyPull.class);
+
+ /**
+ * Constructor.
+ * @param output The output stream to which the pretty-printed document should be sent.
+ * @param catalog The location of a catalog file that should be used to find the Dtd for this document.
+ * This may be null.
+ */
+ public ForayPrettyPull(final OutputStream output, final String catalog) {
+ this.config = new ForayPrettyConfig();
+ if (catalog != null) {
+ this.config.setCatalogs(new String[] {catalog});
+ }
+ this.prettyOutput = new ForayPrettyOutput(output, config);
+ }
+
+ /**
+ * Parses the input document and writes the output document.
+ * @param inputSource The input document to be processed.
+ * @throws XMLStreamException For parsing errors.
+ * @throws IOException For errors reading input or writing output.
+ */
+ public void parse(final InputSource inputSource) throws XMLStreamException, IOException {
+ // final EntityResolver entityResolver = SaxUtils.getEntityResolver(this.config.getCatalogs());
+ // final XMLReader parser = createSax2Parser(true, true, true, entityResolver, true);
+
+ process(inputSource.getByteStream());
+ this.prettyOutput.closeOutput();
+ }
+
+ /**
+ * Parses the input document.
+ * @param inputStream The content to be parsed.
+ * @throws XMLStreamException For parsing errors.
+ */
+ private void process(final InputStream inputStream) throws XMLStreamException {
+
+ final XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
+
+ // https://rules.sonarsource.com/java/RSPEC-2755
+ // prevent xxe
+ xmlInputFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+ xmlInputFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
+
+ this.reader = xmlInputFactory.createXMLEventReader(inputStream);
+ iterate(reader);
+ }
+
+ @Override
+ public void processStartElement(final StartElement startElement) {
+ this.prettyOutput.write(startElement.getName().getLocalPart());
+ this.prettyOutput.write(this.prettyOutput.getConfig().getLineTerminator());
+ }
+
+ /**
+ * Returns the command-line options for the {@link #main(String[])} method.
+ * @return Command-line options.
+ */
+ private static Options getCommandLineOptions() {
+ final Options clOptions = new Options();
+ final Option input = new Option("i", "input", true, "path to the input file");
+ input.setRequired(true);
+ final Option output = new Option("o", "output", true, "path to the output (pretty-printed) file");
+ output.setRequired(true);
+ final Option catalog = new Option("c", "catalog", true, "path to the OASIS XML catalog");
+ output.setRequired(true);
+ clOptions.addOption(input);
+ clOptions.addOption(output);
+ clOptions.addOption(catalog);
+ return clOptions;
+ }
+
+ /**
+ * Command-line interface for pretty-printing an XML document.
+ *
+ * <p>Design Note: We use files instead of URLs here to more easily integrate with desktop tools such as XML
+ * editors, which typically know how to pass parameters for local files, but not how to convert them to URLs.
+ * If URLs are needed, additional flags probably need to be added to the command-line interface to designate
+ * that.</p>
+ *
+ * <p>Return status is one of:</p>
+ * <ul>
+ * <li>0 (success)</li>
+ * <li>1 (wrong quantity of arguments)</li>
+ * <li>2 (file not found)</li>
+ * <li>3 (parsing error)</li>
+ * </ul>
+ *
+ * @param args command-line arguments.
+ * Argument 1 is the location of the input file.
+ * Argument 2 is the location of the output file.
+ * Argument 3 is an optional location of an OASIS-compliant catalog file that can be used to locate local DTDs.
+ */
+ public static void main(final String[] args) {
+ final Logger logger = LoggerFactory.getLogger(ForayPrettyPush.class);
+ final Options commandLineOptions = ForayPrettyPull.getCommandLineOptions();
+ final CommandLineParser commandLineParser = new DefaultParser();
+ CommandLine parsedCommandLine = null;
+ try {
+ parsedCommandLine = commandLineParser.parse(commandLineOptions, args);
+ } catch (final ParseException e) {
+ logger.error(e.getMessage(), e);
+ final HelpFormatter helpFormatter = new HelpFormatter();
+ helpFormatter.printHelp("java -cp $FORAY_CLASSPATH " + ForayPrettyPush.class.getName(), commandLineOptions,
+ true);
+ /* CheckStyle: Allow System.exit() in main method. */
+ System.exit(ForayPrettyPush.STATUS_COMMAND_LINE_ERROR);
+ }
+
+ final String input = parsedCommandLine.getOptionValue("input");
+ final String output = parsedCommandLine.getOptionValue("output");
+ final String catalog = parsedCommandLine.getOptionValue("catalog");
+
+ InputStream inputStream = null;
+ try {
+ FileInputStream fis = null;
+ fis = new FileInputStream(input);
+ inputStream = new BufferedInputStream(fis);
+ } catch (final FileNotFoundException e) {
+ logger.error("File cannot be opened for input: " + input, e);
+ /* CheckStyle: Allow System.exit() in main method. */
+ System.exit(ForayPrettyPush.STATUS_FILE_NOT_FOUND);
+ }
+ final InputSource inputSource = new InputSource(inputStream);
+ OutputStream outputStream = null;
+ try {
+ final FileOutputStream fos = new FileOutputStream(output);
+ outputStream = new BufferedOutputStream(fos);
+ } catch (final FileNotFoundException e) {
+ logger.error("File cannot be opened for output: " + output, e);
+ /* CheckStyle: Allow System.exit() in main method. */
+ System.exit(ForayPrettyPush.STATUS_FILE_NOT_FOUND);
+ }
+ final ForayPrettyPull processor = new ForayPrettyPull(outputStream, catalog);
+ try {
+ processor.parse(inputSource);
+ } catch (final IOException | XMLStreamException e) {
+ logger.error("Error parsing " + input, e);
+ /* CheckStyle: Allow System.exit() in main method. */
+ System.exit(ForayPrettyPush.STATUS_PARSING_ERROR);
+ }
+ logger.info("Input: " + input + " successfully pretty-printed,\n output in: " + output);
+ }
+
+}
Property changes on: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPull.java
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Rev
\ No newline at end of property
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java 2023-02-04 16:26:50 UTC (rev 13119)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java 2023-02-04 18:52:07 UTC (rev 13120)
@@ -78,6 +78,9 @@
/** The configuration for this pretty-printer. */
private ForayPrettyConfig config;
+ /** A output for this pretty-printer. */
+ private ForayPrettyOutput prettyOutput;
+
/** A reusable buffer. */
private StringBuilder charBuffer = new StringBuilder();
@@ -87,9 +90,6 @@
/** The element stack. */
private ElementStack elementStack = new ElementStack();
- /** A output for this pretty-printer. */
- private ForayPrettyOutput prettyOutput;
-
/* Begin state variables. */
/** State variable tracking whether we are currently inside the Dtd or not. */
Added: trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxIterator.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxIterator.java (rev 0)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxIterator.java 2023-02-04 18:52:07 UTC (rev 13120)
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2023 The FOray Project.
+ * http://www.foray.org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This work is in part derived from the following work(s), used with the
+ * permission of the licensor:
+ * Apache FOP, licensed by the Apache Software Foundation
+ *
+ */
+
+/*
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ * $LastChangedBy$
+ */
+
+package org.foray.xml;
+
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.Characters;
+import javax.xml.stream.events.Comment;
+import javax.xml.stream.events.DTD;
+import javax.xml.stream.events.EndDocument;
+import javax.xml.stream.events.EndElement;
+import javax.xml.stream.events.EntityDeclaration;
+import javax.xml.stream.events.EntityReference;
+import javax.xml.stream.events.Namespace;
+import javax.xml.stream.events.NotationDeclaration;
+import javax.xml.stream.events.ProcessingInstruction;
+import javax.xml.stream.events.StartDocument;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+
+/**
+ * Boilerplate code for XML parsers using the StAX iterator API.
+ */
+public interface StaxIterator {
+
+ /**
+ * Iterates the events parsed from an XML event reader.
+ * @param reader The XML event reader providing the events for the document being parsed.
+ * @throws XMLStreamException For errors during parsing.
+ */
+ default void iterate(final XMLEventReader reader) throws XMLStreamException {
+ while (reader.hasNext()) {
+ final XMLEvent event = reader.nextEvent();
+ switch (event.getEventType()) {
+ case XMLEvent.START_ELEMENT: {
+ final StartElement startElement = event.asStartElement();
+ processStartElement(startElement);
+ break;
+ }
+ case XMLEvent.END_ELEMENT: {
+ final EndElement endElement = event.asEndElement();
+ processEndElement(endElement);
+ break;
+ }
+ case XMLEvent.PROCESSING_INSTRUCTION: {
+ final ProcessingInstruction pi = (ProcessingInstruction) event;
+ processProcessingInstruction(pi);
+ break;
+ }
+ case XMLEvent.CHARACTERS:
+ final Characters characters = event.asCharacters();
+ processCharacters(characters);
+ break;
+ case XMLEvent.COMMENT:
+ final Comment comment = (Comment) event;
+ processComment(comment);
+ break;
+ case XMLEvent.SPACE: {
+ processSpace(event);
+ break;
+ }
+ case XMLEvent.START_DOCUMENT: {
+ final StartDocument startDocument = (StartDocument) event;
+ processStartDocument(startDocument);
+ break;
+ }
+ case XMLEvent.END_DOCUMENT: {
+ final EndDocument endDocument = (EndDocument) event;
+ processEndDocument(endDocument);
+ break;
+ }
+ case XMLEvent.ENTITY_REFERENCE: {
+ final EntityReference entityReference = (EntityReference) event;
+ processEntityReference(entityReference);
+ break;
+ }
+ case XMLEvent.ATTRIBUTE: {
+ final Attribute attribute = (Attribute) event;
+ processAttribute(attribute);
+ break;
+ }
+ case XMLEvent.DTD: {
+ final DTD dtd = (DTD) event;
+ processDtd(dtd);
+ break;
+ }
+ case XMLEvent.CDATA: {
+ processCdata(event);
+ break;
+ }
+ case XMLEvent.NAMESPACE: {
+ final Namespace namespace = (Namespace) event;
+ processNamespace(namespace);
+ break;
+ }
+ case XMLEvent.NOTATION_DECLARATION: {
+ final NotationDeclaration notationDeclaration = (NotationDeclaration) event;
+ processNotationDeclaration(notationDeclaration);
+ break;
+ }
+ case XMLEvent.ENTITY_DECLARATION: {
+ final EntityDeclaration entityDeclaration = (EntityDeclaration) event;
+ processEntityDeclaration(entityDeclaration);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Process a "start element" event.
+ * @param startElement The event being processed.
+ */
+ default void processStartElement(StartElement startElement) {
+ }
+
+ /**
+ * Process an "end element" event.
+ * @param endElement The event being processed.
+ */
+ default void processEndElement(final EndElement endElement) {
+ }
+
+ /**
+ * Process an "processing instruction" event.
+ * @param pi The event being processed.
+ */
+ default void processProcessingInstruction(final ProcessingInstruction pi) {
+ }
+
+ /**
+ * Process a "characters" event.
+ * @param characters The event being processed.
+ */
+ default void processCharacters(final Characters characters) {
+ }
+
+ /**
+ * Process a "comment" event.
+ * @param comment The event being processed.
+ */
+ default void processComment(final Comment comment) {
+ }
+
+ /**
+ * Process a "space" event (ignorable whitespace).
+ * @param event The event being processed.
+ */
+ default void processSpace(final XMLEvent event) {
+ /* Ignorable whitespace. Just ignore it. */
+ }
+
+ /**
+ * Process a "start document" event.
+ * @param startDocument The event being processed.
+ */
+ default void processStartDocument(final StartDocument startDocument) {
+ }
+
+ /**
+ * Process an "end document" event.
+ * @param endDocument The event being processed.
+ */
+ default void processEndDocument(final EndDocument endDocument) {
+ }
+
+ /**
+ * Process an "entity reference" event.
+ * @param entityReference The event being processed.
+ */
+ default void processEntityReference(final EntityReference entityReference) {
+ }
+
+ /**
+ * Process an "attribute" event.
+ * @param attribute The event being processed.
+ */
+ default void processAttribute(final Attribute attribute) {
+ }
+
+ /**
+ * Process a "DTD" event.
+ * @param dtd The event being processed.
+ */
+ default void processDtd(final DTD dtd) {
+ }
+
+ /**
+ * Process a "CDATA" event.
+ * @param event The event being processed.
+ */
+ default void processCdata(final XMLEvent event) {
+ }
+
+ /**
+ * Process a "namespace" event.
+ * @param namespace The event being processed.
+ */
+ default void processNamespace(final Namespace namespace) {
+ }
+
+ /**
+ * Process a "notation declaration" event.
+ * @param notationDeclaration The event being processed.
+ */
+ default void processNotationDeclaration(final NotationDeclaration notationDeclaration) {
+ }
+
+ /**
+ * Process a "entity declaration" event.
+ * @param entityDeclaration The event being processed.
+ */
+ default void processEntityDeclaration(final EntityDeclaration entityDeclaration) {
+ }
+
+
+}
Property changes on: trunk/foray/foray-xml/src/main/java/org/foray/xml/StaxIterator.java
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Rev
\ No newline at end of property
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-02-04 16:26:52
|
Revision: 13119
http://sourceforge.net/p/foray/code/13119
Author: victormote
Date: 2023-02-04 16:26:50 +0000 (Sat, 04 Feb 2023)
Log Message:
-----------
Rename ForayPrettyQueue to ForayPrettyOutput for clarity.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java
Added Paths:
-----------
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyOutput.java
Removed Paths:
-------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyQueue.java
Copied: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyOutput.java (from rev 13118, trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyQueue.java)
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyOutput.java (rev 0)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyOutput.java 2023-02-04 16:26:50 UTC (rev 13119)
@@ -0,0 +1,496 @@
+/*
+ * Copyright 2023 The FOray Project.
+ * http://www.foray.org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This work is in part derived from the following work(s), used with the
+ * permission of the licensor:
+ * Apache FOP, licensed by the Apache Software Foundation
+ *
+ */
+
+/*
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ * $LastChangedBy$
+ */
+
+package org.foray.xml;
+
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The queue of unprocessed document pieces during pretty-printing.
+ */
+public class ForayPrettyOutput {
+
+ /** The output stream to which the pretty-printed output should be sent. */
+ private OutputStream output;
+
+ /** The configuration for this pretty-print operation. */
+ private ForayPrettyConfig config;
+
+ /** Collection of Strings that need to be written as soon as we know enough of what comes after them to choose
+ * line breaks.
+ * This is needed for PCDATA and inline tags that must stay on the current line.
+ * It is tempting to turn this all into one long {@link StringBuilder}, but we need to handle attributes
+ * differently from PCDATA. */
+ private List<String> toWriteQueue = new ArrayList<String>();
+
+ /** After running listBreakOpportunities, this array, along with {@link #breakOpportunityIndexes}, holds a list
+ * of break opportunities.
+ * This array contains a list of items in toWriteQueue. */
+ private int[] breakOpportunityItems;
+
+ /** After running listBreakOpportunities, this array, along with {@link #breakOpportunityItems}, holds a list of
+ * break opportunities.
+ * This array points to a specific character in the "items" array. */
+ private int[] breakOpportunityIndexes;
+
+ /** List of Integer indexes into the breakOpportunity arrays that indicate which opportunities have actually
+ * been chosen. */
+ private List<Integer> breaksChosen = new ArrayList<Integer>();
+
+ /** The last column number that was written. This value is one-based, i.e. after the first character is written on a
+ * new line, this value should be 1. */
+ private int lastColumnWritten = 0;
+
+ /**
+ * Constructor.
+ * @param output The output stream to which the output document should be written.
+ * @param config The configuration for this pretty-print operation.
+ */
+ public ForayPrettyOutput(final OutputStream output, final ForayPrettyConfig config) {
+ this.output = output;
+ this.config = config;
+ }
+
+ /**
+ * Flushes all items out of the queue by writing them.
+ */
+ void flush() {
+ if (attemptWriteAll()) {
+ return;
+ }
+ this.listBreakOpportunities();
+ this.chooseBreaks();
+ this.writeChosenChunks();
+ this.reset();
+ }
+
+ /**
+ * Computes the places in the queue where line breaks should occur.
+ */
+ private void chooseBreaks() {
+ this.breaksChosen.clear();
+
+ if (this.breakOpportunityIndexes.length < 1) {
+ return;
+ }
+
+ /* Loop one extra time to catch the last chunk. */
+ for (int i = 0; i <= this.breakOpportunityIndexes.length; i++) {
+ int sizeIfAccepted = 0;
+ /* If it is the first item, we must consider what has already been written on the line. */
+ if (this.breaksChosen.size() < 1) {
+ sizeIfAccepted += this.lastColumnWritten;
+ }
+ final int firstChunkToConsider = this.getLastBreakChosen();
+ sizeIfAccepted += this.chunkSize(firstChunkToConsider, i);
+ if (sizeIfAccepted > this.config.getDesiredLineLength()) {
+ int breakSelected = i - 1;
+ if (breakSelected <= this.getLastBreakChosen()) {
+ /* Don't let the same break get chosen again. If the content is too long, we still need to write
+ * it once. */
+ breakSelected = this.getLastBreakChosen() + 1;
+ }
+ this.breaksChosen.add(breakSelected);
+ }
+ }
+ }
+
+ /**
+ * If everything can be written on the current line, do it.
+ * Otherwise, do nothing.
+ * @return True if everything was written, false otherwise.
+ */
+ private boolean attemptWriteAll() {
+ /* If they all fit on the current line, write them all. */
+ if (charCount() + this.lastColumnWritten <= this.config.getDesiredLineLength()) {
+ writeAll();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Writes all items in the queue.
+ */
+ private void writeAll() {
+ while (this.toWriteQueue.size() > 0) {
+ final String returnItem = this.toWriteQueue.get(0);
+ writeRawPCDATA(returnItem);
+ this.toWriteQueue.remove(0);
+ }
+ reset();
+ }
+
+ /**
+ * Resets the queue to an empty state.
+ */
+ private void reset() {
+ this.breakOpportunityItems = null;
+ this.breakOpportunityIndexes = null;
+ this.toWriteQueue.clear();
+ this.breaksChosen.clear();
+ }
+
+ /**
+ * Adds an item to the queue.
+ * @param itemToAdd The item to be added to the queue.
+ */
+ protected void add(final String itemToAdd) {
+ if (itemToAdd == null) {
+ return;
+ }
+ this.toWriteQueue.add(itemToAdd);
+ }
+
+ /**
+ * Returns a specific item from the queue.
+ * @param index The index of the item to be returned.
+ * @return The specified item.
+ */
+ protected String get(final int index) {
+ if (index > this.toWriteQueue.size()) {
+ return null;
+ }
+ return this.toWriteQueue.get(index);
+ }
+
+ /**
+ * Returns the number of characters to be written from the queue.
+ * @return The number of characters to be written from the queue.
+ */
+ private int charCount() {
+ int charCount = 0;
+ for (int i = 0; i < this.toWriteQueue.size(); i++) {
+ final String string = get(i);
+ charCount += string.length();
+ }
+ return charCount;
+ }
+
+ /**
+ * For all chunks that have been selected, writes them.
+ */
+ private void writeChosenChunks() {
+ /* If there are no breaks, there is nothing to do but write the
+ * whole thing.*/
+ if (this.breaksChosen.size() < 0) {
+ this.writeAll();
+ return;
+ }
+
+ for (int i = 0; i < this.breaksChosen.size(); i++) {
+ this.writeChunk(i, true);
+ }
+ /* Write the last chunk. Don't write a new-line after it. That will
+ * be controlled at a higher level. */
+ this.writeChunk(Integer.MAX_VALUE, false);
+ }
+
+ /**
+ * Returns the value for a specific chosen item.
+ * @param index The index to the chosen break.
+ * @return The break value.
+ */
+ private int getBreakChosen(final int index) {
+ if (this.breaksChosen == null
+ || index < 0
+ || index >= this.breaksChosen.size()) {
+ return -1;
+ }
+ final Object object = this.breaksChosen.get(index);
+ final Integer integer = (Integer) object;
+ return integer.intValue();
+ }
+
+ /**
+ * Returns the value for the last break chosen.
+ * @return The value for the last break chosen.
+ */
+ private int getLastBreakChosen() {
+ final int lastIndex = this.breaksChosen.size() - 1;
+ return getBreakChosen(lastIndex);
+ }
+
+ /**
+ * Computes the break opportunies, caching them in member variables.
+ */
+ private void listBreakOpportunities() {
+ int count = countBreakOpportunities();
+ this.breakOpportunityItems = new int[count];
+ this.breakOpportunityIndexes = new int[count];
+ if (count == 0) {
+ return;
+ }
+ count = 0;
+ for (int i = 0; i < this.toWriteQueue.size(); i++) {
+ final String string = this.get(i);
+ for (int j = 0; j < string.length(); j++) {
+ final char c = string.charAt(j);
+ if (c == ' ') {
+ this.breakOpportunityItems[count] = i;
+ this.breakOpportunityIndexes[count] = j;
+ count ++;
+ }
+ }
+ }
+ count = this.breakOpportunityItems.length;
+ }
+
+ /**
+ * Computes the size of a chunk.
+ * @param startOpportunity The starting break opportunity.
+ * @param endOpportunity The ending break opportunity.
+ * @return The size, in chars, of the chunk delimited.
+ */
+ private int chunkSize(final int startOpportunity,
+ final int endOpportunity) {
+ if (startOpportunity == endOpportunity) {
+ return 0;
+ }
+ final int startItem;
+ final int startItemIndex;
+ final int endItem;
+ final int endItemIndex;
+ if (startOpportunity < 0) {
+ startItem = 0;
+ startItemIndex = -1;
+ } else {
+ startItem = this.breakOpportunityItems[startOpportunity];
+ startItemIndex = this.breakOpportunityIndexes[startOpportunity];
+ }
+ final int lastOpportunity = this.breakOpportunityItems.length - 1;
+ if (endOpportunity > lastOpportunity) {
+ endItem = this.toWriteQueue.size() - 1;
+ final String string = this.get(endItem);
+ endItemIndex = string.length();
+ } else {
+ endItem = this.breakOpportunityItems[endOpportunity];
+ endItemIndex = this.breakOpportunityIndexes[endOpportunity];
+ }
+ int size = 0;
+ for (int i = startItem; i <= endItem; i++) {
+ int startIndex = 0;
+ int endIndex = 0;
+ if (i == startItem) {
+ startIndex = startItemIndex;
+ }
+ if (i == endItem) {
+ endIndex = endItemIndex - 1;
+ } else {
+ final String item = this.get(i);
+ endIndex = item.length() - 1;
+ }
+ size += endIndex - startIndex;
+ if (i != startItem) {
+ /* For all but the first item, we must add the space that
+ * separates the chunks in order to get the complete size.*/
+ size ++;
+ }
+ }
+ return size;
+ }
+
+ /**
+ * Returns the number of break opportunities.
+ * @return The number of break opportunities.
+ */
+ private int countBreakOpportunities() {
+ int count = 0;
+ for (int i = 0; i < this.toWriteQueue.size(); i++) {
+ final String string = this.get(i);
+ for (int j = 0; j < string.length(); j++) {
+ final char c = string.charAt(j);
+ if (c == ' ') {
+ count ++;
+ }
+ }
+ }
+ return count;
+ }
+
+ /**
+ * Write one of the chunks selected.
+ * @param breakSelected The break selection that should be written.
+ * @param newLine Set to true if a new-line should be written after the text of the line.
+ */
+ private void writeChunk(final int breakSelected, final boolean newLine) {
+ final int startOpportunity;
+ final int endOpportunity;
+ if (breakSelected == 0) {
+ startOpportunity = Integer.MIN_VALUE;
+ endOpportunity = this.getBreakChosen(breakSelected);
+ } else if (breakSelected > this.breaksChosen.size() - 1) {
+ startOpportunity = this.getLastBreakChosen();
+ endOpportunity = Integer.MAX_VALUE;
+ } else {
+ startOpportunity = this.getBreakChosen(breakSelected - 1);
+ endOpportunity = this.getBreakChosen(breakSelected);
+ }
+
+ final int startItem;
+ final int startItemIndex;
+ final int endItem;
+ final int endItemIndex;
+ if (startOpportunity < 0) {
+ startItem = 0;
+ startItemIndex = 0;
+ } else {
+ startItem = this.breakOpportunityItems[startOpportunity];
+ startItemIndex = this.breakOpportunityIndexes[startOpportunity];
+ }
+ if (endOpportunity >= this.breakOpportunityIndexes.length) {
+ final int lastItem = this.toWriteQueue.size() - 1;
+ endItem = lastItem;
+ final String lastString = this.getLastItem();
+ if (lastString == null) {
+ endItemIndex = -1;
+ } else {
+ endItemIndex = lastString.length() - 1;
+ }
+ } else {
+ endItem = this.breakOpportunityItems[endOpportunity];
+ endItemIndex = this.breakOpportunityIndexes[endOpportunity];
+ }
+ for (int i = startItem; i <= endItem; i++) {
+ final String string = this.get(i);
+ int startIndex = 0;
+ if (i == startItem) {
+ startIndex = startItemIndex;
+ /* If the first character on a line is a space, don't write
+ * it. */
+ if (string.charAt(startIndex) == ' '
+ && this.lastColumnWritten == 0) {
+ startIndex ++;
+ }
+ }
+ int endIndex = string.length() - 1;
+ if (i == endItem) {
+ endIndex = endItemIndex;
+ if (string.charAt(endIndex) == ' ') {
+ endIndex --;
+ }
+ }
+ if (startIndex > -1
+ && endIndex > -1) {
+ final String stringToWrite = string.substring(startIndex, endIndex + 1);
+ write(stringToWrite);
+ }
+ }
+ if (newLine) {
+ write(this.config.getLineTerminator());
+ }
+ }
+
+ /**
+ * Returns the last item from the queue.
+ * @return The last item from the queue.
+ */
+ private String getLastItem() {
+ if (this.toWriteQueue.size() < 1) {
+ return null;
+ }
+ final int lastIndex = this.toWriteQueue.size() - 1;
+ return this.toWriteQueue.get(lastIndex);
+ }
+
+ /**
+ * Closes the output stream.
+ * @throws IOException For errors closing output stream.
+ */
+ void closeOutput() throws IOException {
+ this.output.close();
+ }
+
+ /**
+ * Use this method if the content may contain \n characters that need to be converted to the output line-ending.
+ * SAX converts all line-endings, regardless of platform, to \n.
+ * Do not use this method for output that has specified line-endings in it, as that may result in the conversion of
+ * \r\n to \r\r\n, for example.
+ * @param outputString The String that should be written.
+ */
+ void writeRawPCDATA(final String outputString) {
+ if (this.config.getLineTerminator().equals("\n")) {
+ /* The specified line terminator is the same as that used in the input. Just write it. */
+ write(outputString);
+ return;
+ }
+ final int lastLineBreakIndex = outputString.lastIndexOf("\n");
+ if (lastLineBreakIndex < 0) {
+ /* No line breaks in what is being written. Just write it. */
+ write(outputString);
+ return;
+ }
+ final StringBuilder buffer = new StringBuilder(outputString);
+ int bufferIndex = 0;
+ while (bufferIndex < buffer.length()) {
+ if (buffer.charAt(bufferIndex) == '\n') {
+ buffer.replace(bufferIndex, bufferIndex + 1, this.config.getLineTerminator());
+ bufferIndex += this.config.getLineTerminator().length();
+ } else {
+ bufferIndex ++;
+ }
+ }
+ write(buffer.toString());
+ }
+
+ /**
+ * Writes an output String.
+ * @param outputString The output to be written.
+ */
+ void write(final String outputString) {
+ if (outputString == null) {
+ return;
+ }
+ if (outputString.length() < 1) {
+ return;
+ }
+ try {
+ this.output.write(outputString.getBytes(this.config.getOutputEncoding()));
+ /* Following line for debugging only */
+ this.output.flush();
+ } catch (final IOException e) {
+ LoggerFactory.getLogger(this.getClass()).error("Error converting text.");
+ }
+ final int lastLineBreakIndex = outputString.lastIndexOf(this.config.getLineTerminator());
+ if (lastLineBreakIndex < 0) {
+ /* No line breaks in what is being written. Increment the current
+ * column by the length of outputString. Note that we want the
+ * count of characters, not bytes, here. */
+ this.lastColumnWritten += outputString.length();
+ } else {
+ this.lastColumnWritten = outputString.length() - lastLineBreakIndex
+ - this.config.getLineTerminator().length();
+ }
+ }
+
+}
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java 2023-02-04 16:24:13 UTC (rev 13118)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java 2023-02-04 16:26:50 UTC (rev 13119)
@@ -87,8 +87,8 @@
/** The element stack. */
private ElementStack elementStack = new ElementStack();
- /** A queue of unprocessed elements. */
- private ForayPrettyQueue queue;
+ /** A output for this pretty-printer. */
+ private ForayPrettyOutput prettyOutput;
/* Begin state variables. */
@@ -124,7 +124,7 @@
if (catalog != null) {
this.config.setCatalogs(new String[] {catalog});
}
- this.queue = new ForayPrettyQueue(output, config);
+ this.prettyOutput = new ForayPrettyOutput(output, config);
}
@Override
@@ -142,7 +142,7 @@
*/
private void cleanup() {
try {
- this.queue.closeOutput();
+ this.prettyOutput.closeOutput();
} catch (final IOException e1) {
/* Ignore. */
}
@@ -150,13 +150,13 @@
@Override
public void startDocument() {
- this.queue.write(this.config.getXmlDeclaration());
- this.queue.write(this.config.getLineTerminator());
+ this.prettyOutput.write(this.config.getXmlDeclaration());
+ this.prettyOutput.write(this.config.getLineTerminator());
}
@Override
public void endDocument() {
- this.queue.write(this.config.getLineTerminator());
+ this.prettyOutput.write(this.config.getLineTerminator());
}
@Override
@@ -216,7 +216,7 @@
if (qName.equals(this.rootElement)) {
/* Whitespace before and after the end of the root element is
* discarded by SAX, so we need to control it manually. */
- this.queue.write(this.config.getPreRootText());
+ this.prettyOutput.write(this.config.getPreRootText());
}
/* Accumulate the tag opener. */
@@ -248,19 +248,19 @@
/* If starting on new line, write the tag open buffer. */
if (this.startTagOnNewLine()) {
- this.queue.flush();
- this.queue.write(this.config.getLineTerminator());
+ this.prettyOutput.flush();
+ this.prettyOutput.write(this.config.getLineTerminator());
if (this.shouldIndent()) {
- this.queue.write(indent());
+ this.prettyOutput.write(indent());
}
- this.queue.write(tagOpenBuffer.toString());
+ this.prettyOutput.write(tagOpenBuffer.toString());
} else {
/* Otherwise queue it up. */
- this.queue.add(tagOpenBuffer.toString());
+ this.prettyOutput.add(tagOpenBuffer.toString());
}
/* Queue up the attributes and tag close. */
- this.queue.add(attributesBuffer.toString() + tagCloseBuffer.toString());
+ this.prettyOutput.add(attributesBuffer.toString() + tagCloseBuffer.toString());
}
/**
@@ -298,13 +298,13 @@
if (this.topElementWritten) {
if (endTagOnNewLine()) {
- this.queue.flush();
- this.queue.write(this.config.getLineTerminator());
- this.queue.write(indent());
+ this.prettyOutput.flush();
+ this.prettyOutput.write(this.config.getLineTerminator());
+ this.prettyOutput.write(indent());
}
- this.queue.add("</" + qName + ">");
+ this.prettyOutput.add("</" + qName + ">");
if (endTagOnNewLine()) {
- this.queue.flush();
+ this.prettyOutput.flush();
}
} else {
/* Element was empty. */
@@ -313,7 +313,7 @@
if (qName.equals(this.rootElement)) {
/* Whitespace before and after the end of the root element is
* discarded by SAX, so we need to control it manually. */
- this.queue.write(this.config.getPostRootText());
+ this.prettyOutput.write(this.config.getPostRootText());
}
this.elementStack.pop();
}
@@ -362,13 +362,13 @@
}
ensureTopElementWritten(false);
if (this.inCdata) {
- this.queue.writeRawPCDATA(this.charBuffer.toString());
+ this.prettyOutput.writeRawPCDATA(this.charBuffer.toString());
} else if (this.config.isBreakPCDATA()) {
/* Note: SAX input has linefeeds normalized to \n. */
XmlUtils.normalizeWhitespace(this.charBuffer);
- this.queue.add(this.charBuffer.toString());
+ this.prettyOutput.add(this.charBuffer.toString());
} else {
- this.queue.writeRawPCDATA(this.charBuffer.toString());
+ this.prettyOutput.writeRawPCDATA(this.charBuffer.toString());
}
this.charBuffer.setLength(0);
}
@@ -375,8 +375,8 @@
@Override
public void processingInstruction(final String target, final String data) {
- this.queue.write(target);
- this.queue.write(data);
+ this.prettyOutput.write(target);
+ this.prettyOutput.write(data);
}
@Override
@@ -391,11 +391,11 @@
}
flushCharacters();
ensureTopElementWritten(false);
- this.queue.flush();
- this.queue.write("<!--");
+ this.prettyOutput.flush();
+ this.prettyOutput.write("<!--");
final String comment = new String(buffer, offset, length);
- this.queue.writeRawPCDATA(comment);
- this.queue.write("-->");
+ this.prettyOutput.writeRawPCDATA(comment);
+ this.prettyOutput.write("-->");
}
@Override
@@ -402,8 +402,8 @@
public void startCDATA() throws SAXException {
flushCharacters();
ensureTopElementWritten(false);
- this.queue.flush();
- this.queue.writeRawPCDATA("<![CDATA[");
+ this.prettyOutput.flush();
+ this.prettyOutput.writeRawPCDATA("<![CDATA[");
this.inCdata = true;
}
@@ -412,7 +412,7 @@
flushCharacters();
ensureTopElementWritten(false);
// this.queue.flush();
- this.queue.writeRawPCDATA("]]>");
+ this.prettyOutput.writeRawPCDATA("]]>");
this.inCdata = false;
}
@@ -439,7 +439,7 @@
builder.append("\"" + systemId + "\"");
builder.append(">");
builder.append(this.config.getLineTerminator());
- this.queue.write(builder.toString());
+ this.prettyOutput.write(builder.toString());
this.inDTD = true;
this.rootElement = name;
}
Deleted: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyQueue.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyQueue.java 2023-02-04 16:24:13 UTC (rev 13118)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyQueue.java 2023-02-04 16:26:50 UTC (rev 13119)
@@ -1,496 +0,0 @@
-/*
- * Copyright 2023 The FOray Project.
- * http://www.foray.org
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * This work is in part derived from the following work(s), used with the
- * permission of the licensor:
- * Apache FOP, licensed by the Apache Software Foundation
- *
- */
-
-/*
- * $LastChangedRevision$
- * $LastChangedDate$
- * $LastChangedBy$
- */
-
-package org.foray.xml;
-
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * The queue of unprocessed document pieces during pretty-printing.
- */
-public class ForayPrettyQueue {
-
- /** The output stream to which the pretty-printed output should be sent. */
- private OutputStream output;
-
- /** The configuration for this pretty-print operation. */
- private ForayPrettyConfig config;
-
- /** Collection of Strings that need to be written as soon as we know enough of what comes after them to choose
- * line breaks.
- * This is needed for PCDATA and inline tags that must stay on the current line.
- * It is tempting to turn this all into one long {@link StringBuilder}, but we need to handle attributes
- * differently from PCDATA. */
- private List<String> toWriteQueue = new ArrayList<String>();
-
- /** After running listBreakOpportunities, this array, along with {@link #breakOpportunityIndexes}, holds a list
- * of break opportunities.
- * This array contains a list of items in toWriteQueue. */
- private int[] breakOpportunityItems;
-
- /** After running listBreakOpportunities, this array, along with {@link #breakOpportunityItems}, holds a list of
- * break opportunities.
- * This array points to a specific character in the "items" array. */
- private int[] breakOpportunityIndexes;
-
- /** List of Integer indexes into the breakOpportunity arrays that indicate which opportunities have actually
- * been chosen. */
- private List<Integer> breaksChosen = new ArrayList<Integer>();
-
- /** The last column number that was written. This value is one-based, i.e. after the first character is written on a
- * new line, this value should be 1. */
- private int lastColumnWritten = 0;
-
- /**
- * Constructor.
- * @param output The output stream to which the output document should be written.
- * @param config The configuration for this pretty-print operation.
- */
- public ForayPrettyQueue(final OutputStream output, final ForayPrettyConfig config) {
- this.output = output;
- this.config = config;
- }
-
- /**
- * Flushes all items out of the queue by writing them.
- */
- void flush() {
- if (attemptWriteAll()) {
- return;
- }
- this.listBreakOpportunities();
- this.chooseBreaks();
- this.writeChosenChunks();
- this.reset();
- }
-
- /**
- * Computes the places in the queue where line breaks should occur.
- */
- private void chooseBreaks() {
- this.breaksChosen.clear();
-
- if (this.breakOpportunityIndexes.length < 1) {
- return;
- }
-
- /* Loop one extra time to catch the last chunk. */
- for (int i = 0; i <= this.breakOpportunityIndexes.length; i++) {
- int sizeIfAccepted = 0;
- /* If it is the first item, we must consider what has already been written on the line. */
- if (this.breaksChosen.size() < 1) {
- sizeIfAccepted += this.lastColumnWritten;
- }
- final int firstChunkToConsider = this.getLastBreakChosen();
- sizeIfAccepted += this.chunkSize(firstChunkToConsider, i);
- if (sizeIfAccepted > this.config.getDesiredLineLength()) {
- int breakSelected = i - 1;
- if (breakSelected <= this.getLastBreakChosen()) {
- /* Don't let the same break get chosen again. If the content is too long, we still need to write
- * it once. */
- breakSelected = this.getLastBreakChosen() + 1;
- }
- this.breaksChosen.add(breakSelected);
- }
- }
- }
-
- /**
- * If everything can be written on the current line, do it.
- * Otherwise, do nothing.
- * @return True if everything was written, false otherwise.
- */
- private boolean attemptWriteAll() {
- /* If they all fit on the current line, write them all. */
- if (charCount() + this.lastColumnWritten <= this.config.getDesiredLineLength()) {
- writeAll();
- return true;
- }
- return false;
- }
-
- /**
- * Writes all items in the queue.
- */
- private void writeAll() {
- while (this.toWriteQueue.size() > 0) {
- final String returnItem = this.toWriteQueue.get(0);
- writeRawPCDATA(returnItem);
- this.toWriteQueue.remove(0);
- }
- reset();
- }
-
- /**
- * Resets the queue to an empty state.
- */
- private void reset() {
- this.breakOpportunityItems = null;
- this.breakOpportunityIndexes = null;
- this.toWriteQueue.clear();
- this.breaksChosen.clear();
- }
-
- /**
- * Adds an item to the queue.
- * @param itemToAdd The item to be added to the queue.
- */
- protected void add(final String itemToAdd) {
- if (itemToAdd == null) {
- return;
- }
- this.toWriteQueue.add(itemToAdd);
- }
-
- /**
- * Returns a specific item from the queue.
- * @param index The index of the item to be returned.
- * @return The specified item.
- */
- protected String get(final int index) {
- if (index > this.toWriteQueue.size()) {
- return null;
- }
- return this.toWriteQueue.get(index);
- }
-
- /**
- * Returns the number of characters to be written from the queue.
- * @return The number of characters to be written from the queue.
- */
- private int charCount() {
- int charCount = 0;
- for (int i = 0; i < this.toWriteQueue.size(); i++) {
- final String string = get(i);
- charCount += string.length();
- }
- return charCount;
- }
-
- /**
- * For all chunks that have been selected, writes them.
- */
- private void writeChosenChunks() {
- /* If there are no breaks, there is nothing to do but write the
- * whole thing.*/
- if (this.breaksChosen.size() < 0) {
- this.writeAll();
- return;
- }
-
- for (int i = 0; i < this.breaksChosen.size(); i++) {
- this.writeChunk(i, true);
- }
- /* Write the last chunk. Don't write a new-line after it. That will
- * be controlled at a higher level. */
- this.writeChunk(Integer.MAX_VALUE, false);
- }
-
- /**
- * Returns the value for a specific chosen item.
- * @param index The index to the chosen break.
- * @return The break value.
- */
- private int getBreakChosen(final int index) {
- if (this.breaksChosen == null
- || index < 0
- || index >= this.breaksChosen.size()) {
- return -1;
- }
- final Object object = this.breaksChosen.get(index);
- final Integer integer = (Integer) object;
- return integer.intValue();
- }
-
- /**
- * Returns the value for the last break chosen.
- * @return The value for the last break chosen.
- */
- private int getLastBreakChosen() {
- final int lastIndex = this.breaksChosen.size() - 1;
- return getBreakChosen(lastIndex);
- }
-
- /**
- * Computes the break opportunies, caching them in member variables.
- */
- private void listBreakOpportunities() {
- int count = countBreakOpportunities();
- this.breakOpportunityItems = new int[count];
- this.breakOpportunityIndexes = new int[count];
- if (count == 0) {
- return;
- }
- count = 0;
- for (int i = 0; i < this.toWriteQueue.size(); i++) {
- final String string = this.get(i);
- for (int j = 0; j < string.length(); j++) {
- final char c = string.charAt(j);
- if (c == ' ') {
- this.breakOpportunityItems[count] = i;
- this.breakOpportunityIndexes[count] = j;
- count ++;
- }
- }
- }
- count = this.breakOpportunityItems.length;
- }
-
- /**
- * Computes the size of a chunk.
- * @param startOpportunity The starting break opportunity.
- * @param endOpportunity The ending break opportunity.
- * @return The size, in chars, of the chunk delimited.
- */
- private int chunkSize(final int startOpportunity,
- final int endOpportunity) {
- if (startOpportunity == endOpportunity) {
- return 0;
- }
- final int startItem;
- final int startItemIndex;
- final int endItem;
- final int endItemIndex;
- if (startOpportunity < 0) {
- startItem = 0;
- startItemIndex = -1;
- } else {
- startItem = this.breakOpportunityItems[startOpportunity];
- startItemIndex = this.breakOpportunityIndexes[startOpportunity];
- }
- final int lastOpportunity = this.breakOpportunityItems.length - 1;
- if (endOpportunity > lastOpportunity) {
- endItem = this.toWriteQueue.size() - 1;
- final String string = this.get(endItem);
- endItemIndex = string.length();
- } else {
- endItem = this.breakOpportunityItems[endOpportunity];
- endItemIndex = this.breakOpportunityIndexes[endOpportunity];
- }
- int size = 0;
- for (int i = startItem; i <= endItem; i++) {
- int startIndex = 0;
- int endIndex = 0;
- if (i == startItem) {
- startIndex = startItemIndex;
- }
- if (i == endItem) {
- endIndex = endItemIndex - 1;
- } else {
- final String item = this.get(i);
- endIndex = item.length() - 1;
- }
- size += endIndex - startIndex;
- if (i != startItem) {
- /* For all but the first item, we must add the space that
- * separates the chunks in order to get the complete size.*/
- size ++;
- }
- }
- return size;
- }
-
- /**
- * Returns the number of break opportunities.
- * @return The number of break opportunities.
- */
- private int countBreakOpportunities() {
- int count = 0;
- for (int i = 0; i < this.toWriteQueue.size(); i++) {
- final String string = this.get(i);
- for (int j = 0; j < string.length(); j++) {
- final char c = string.charAt(j);
- if (c == ' ') {
- count ++;
- }
- }
- }
- return count;
- }
-
- /**
- * Write one of the chunks selected.
- * @param breakSelected The break selection that should be written.
- * @param newLine Set to true if a new-line should be written after the text of the line.
- */
- private void writeChunk(final int breakSelected, final boolean newLine) {
- final int startOpportunity;
- final int endOpportunity;
- if (breakSelected == 0) {
- startOpportunity = Integer.MIN_VALUE;
- endOpportunity = this.getBreakChosen(breakSelected);
- } else if (breakSelected > this.breaksChosen.size() - 1) {
- startOpportunity = this.getLastBreakChosen();
- endOpportunity = Integer.MAX_VALUE;
- } else {
- startOpportunity = this.getBreakChosen(breakSelected - 1);
- endOpportunity = this.getBreakChosen(breakSelected);
- }
-
- final int startItem;
- final int startItemIndex;
- final int endItem;
- final int endItemIndex;
- if (startOpportunity < 0) {
- startItem = 0;
- startItemIndex = 0;
- } else {
- startItem = this.breakOpportunityItems[startOpportunity];
- startItemIndex = this.breakOpportunityIndexes[startOpportunity];
- }
- if (endOpportunity >= this.breakOpportunityIndexes.length) {
- final int lastItem = this.toWriteQueue.size() - 1;
- endItem = lastItem;
- final String lastString = this.getLastItem();
- if (lastString == null) {
- endItemIndex = -1;
- } else {
- endItemIndex = lastString.length() - 1;
- }
- } else {
- endItem = this.breakOpportunityItems[endOpportunity];
- endItemIndex = this.breakOpportunityIndexes[endOpportunity];
- }
- for (int i = startItem; i <= endItem; i++) {
- final String string = this.get(i);
- int startIndex = 0;
- if (i == startItem) {
- startIndex = startItemIndex;
- /* If the first character on a line is a space, don't write
- * it. */
- if (string.charAt(startIndex) == ' '
- && this.lastColumnWritten == 0) {
- startIndex ++;
- }
- }
- int endIndex = string.length() - 1;
- if (i == endItem) {
- endIndex = endItemIndex;
- if (string.charAt(endIndex) == ' ') {
- endIndex --;
- }
- }
- if (startIndex > -1
- && endIndex > -1) {
- final String stringToWrite = string.substring(startIndex, endIndex + 1);
- write(stringToWrite);
- }
- }
- if (newLine) {
- write(this.config.getLineTerminator());
- }
- }
-
- /**
- * Returns the last item from the queue.
- * @return The last item from the queue.
- */
- private String getLastItem() {
- if (this.toWriteQueue.size() < 1) {
- return null;
- }
- final int lastIndex = this.toWriteQueue.size() - 1;
- return this.toWriteQueue.get(lastIndex);
- }
-
- /**
- * Closes the output stream.
- * @throws IOException For errors closing output stream.
- */
- void closeOutput() throws IOException {
- this.output.close();
- }
-
- /**
- * Use this method if the content may contain \n characters that need to be converted to the output line-ending.
- * SAX converts all line-endings, regardless of platform, to \n.
- * Do not use this method for output that has specified line-endings in it, as that may result in the conversion of
- * \r\n to \r\r\n, for example.
- * @param outputString The String that should be written.
- */
- void writeRawPCDATA(final String outputString) {
- if (this.config.getLineTerminator().equals("\n")) {
- /* The specified line terminator is the same as that used in the input. Just write it. */
- write(outputString);
- return;
- }
- final int lastLineBreakIndex = outputString.lastIndexOf("\n");
- if (lastLineBreakIndex < 0) {
- /* No line breaks in what is being written. Just write it. */
- write(outputString);
- return;
- }
- final StringBuilder buffer = new StringBuilder(outputString);
- int bufferIndex = 0;
- while (bufferIndex < buffer.length()) {
- if (buffer.charAt(bufferIndex) == '\n') {
- buffer.replace(bufferIndex, bufferIndex + 1, this.config.getLineTerminator());
- bufferIndex += this.config.getLineTerminator().length();
- } else {
- bufferIndex ++;
- }
- }
- write(buffer.toString());
- }
-
- /**
- * Writes an output String.
- * @param outputString The output to be written.
- */
- void write(final String outputString) {
- if (outputString == null) {
- return;
- }
- if (outputString.length() < 1) {
- return;
- }
- try {
- this.output.write(outputString.getBytes(this.config.getOutputEncoding()));
- /* Following line for debugging only */
- this.output.flush();
- } catch (final IOException e) {
- LoggerFactory.getLogger(this.getClass()).error("Error converting text.");
- }
- final int lastLineBreakIndex = outputString.lastIndexOf(this.config.getLineTerminator());
- if (lastLineBreakIndex < 0) {
- /* No line breaks in what is being written. Increment the current
- * column by the length of outputString. Note that we want the
- * count of characters, not bytes, here. */
- this.lastColumnWritten += outputString.length();
- } else {
- this.lastColumnWritten = outputString.length() - lastLineBreakIndex
- - this.config.getLineTerminator().length();
- }
- }
-
-}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-02-04 16:24:17
|
Revision: 13118
http://sourceforge.net/p/foray/code/13118
Author: victormote
Date: 2023-02-04 16:24:13 +0000 (Sat, 04 Feb 2023)
Log Message:
-----------
Inject config instead of pretty-printer into the output queue instance.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyQueue.java
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java 2023-02-04 16:13:18 UTC (rev 13117)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java 2023-02-04 16:24:13 UTC (rev 13118)
@@ -124,7 +124,7 @@
if (catalog != null) {
this.config.setCatalogs(new String[] {catalog});
}
- this.queue = new ForayPrettyQueue(this, output);
+ this.queue = new ForayPrettyQueue(output, config);
}
@Override
@@ -479,14 +479,6 @@
return this.elementStack.size() - 1;
}
- /**
- * Returns the configuration for this pretty-printer.
- * @return The configuration for this pretty-printer.
- */
- public ForayPrettyConfig getConfig() {
- return this.config;
- }
-
@Override
public void reset() {
throw new UnsupportedOperationException();
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyQueue.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyQueue.java 2023-02-04 16:13:18 UTC (rev 13117)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyQueue.java 2023-02-04 16:24:13 UTC (rev 13118)
@@ -40,12 +40,12 @@
*/
public class ForayPrettyQueue {
- /** The pretty-printer to which this queue is attached. */
- private ForayPrettyPush pretty;
-
/** The output stream to which the pretty-printed output should be sent. */
private OutputStream output;
+ /** The configuration for this pretty-print operation. */
+ private ForayPrettyConfig config;
+
/** Collection of Strings that need to be written as soon as we know enough of what comes after them to choose
* line breaks.
* This is needed for PCDATA and inline tags that must stay on the current line.
@@ -73,12 +73,12 @@
/**
* Constructor.
- * @param pretty The pretty-printer to which this queue is attached.
* @param output The output stream to which the output document should be written.
+ * @param config The configuration for this pretty-print operation.
*/
- public ForayPrettyQueue(final ForayPrettyPush pretty, final OutputStream output) {
- this.pretty = pretty;
+ public ForayPrettyQueue(final OutputStream output, final ForayPrettyConfig config) {
this.output = output;
+ this.config = config;
}
/**
@@ -113,7 +113,7 @@
}
final int firstChunkToConsider = this.getLastBreakChosen();
sizeIfAccepted += this.chunkSize(firstChunkToConsider, i);
- if (sizeIfAccepted > this.pretty.getConfig().getDesiredLineLength()) {
+ if (sizeIfAccepted > this.config.getDesiredLineLength()) {
int breakSelected = i - 1;
if (breakSelected <= this.getLastBreakChosen()) {
/* Don't let the same break get chosen again. If the content is too long, we still need to write
@@ -132,7 +132,7 @@
*/
private boolean attemptWriteAll() {
/* If they all fit on the current line, write them all. */
- if (charCount() + this.lastColumnWritten <= this.pretty.getConfig().getDesiredLineLength()) {
+ if (charCount() + this.lastColumnWritten <= this.config.getDesiredLineLength()) {
writeAll();
return true;
}
@@ -407,7 +407,7 @@
}
}
if (newLine) {
- write(this.pretty.getConfig().getLineTerminator());
+ write(this.config.getLineTerminator());
}
}
@@ -439,7 +439,7 @@
* @param outputString The String that should be written.
*/
void writeRawPCDATA(final String outputString) {
- if (this.pretty.getConfig().getLineTerminator().equals("\n")) {
+ if (this.config.getLineTerminator().equals("\n")) {
/* The specified line terminator is the same as that used in the input. Just write it. */
write(outputString);
return;
@@ -454,8 +454,8 @@
int bufferIndex = 0;
while (bufferIndex < buffer.length()) {
if (buffer.charAt(bufferIndex) == '\n') {
- buffer.replace(bufferIndex, bufferIndex + 1, this.pretty.getConfig().getLineTerminator());
- bufferIndex += this.pretty.getConfig().getLineTerminator().length();
+ buffer.replace(bufferIndex, bufferIndex + 1, this.config.getLineTerminator());
+ bufferIndex += this.config.getLineTerminator().length();
} else {
bufferIndex ++;
}
@@ -475,13 +475,13 @@
return;
}
try {
- this.output.write(outputString.getBytes(this.pretty.getConfig().getOutputEncoding()));
+ this.output.write(outputString.getBytes(this.config.getOutputEncoding()));
/* Following line for debugging only */
this.output.flush();
} catch (final IOException e) {
LoggerFactory.getLogger(this.getClass()).error("Error converting text.");
}
- final int lastLineBreakIndex = outputString.lastIndexOf(this.pretty.getConfig().getLineTerminator());
+ final int lastLineBreakIndex = outputString.lastIndexOf(this.config.getLineTerminator());
if (lastLineBreakIndex < 0) {
/* No line breaks in what is being written. Increment the current
* column by the length of outputString. Note that we want the
@@ -489,7 +489,7 @@
this.lastColumnWritten += outputString.length();
} else {
this.lastColumnWritten = outputString.length() - lastLineBreakIndex
- - this.pretty.getConfig().getLineTerminator().length();
+ - this.config.getLineTerminator().length();
}
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-02-04 16:13:21
|
Revision: 13117
http://sourceforge.net/p/foray/code/13117
Author: victormote
Date: 2023-02-04 16:13:18 +0000 (Sat, 04 Feb 2023)
Log Message:
-----------
Move more output-related code to ForayPrettyQueue.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyQueue.java
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java 2023-02-04 15:41:37 UTC (rev 13116)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java 2023-02-04 16:13:18 UTC (rev 13117)
@@ -78,9 +78,6 @@
/** The configuration for this pretty-printer. */
private ForayPrettyConfig config;
- /** The output stream to which the pretty-printed output should be sent. */
- private OutputStream output;
-
/** A reusable buffer. */
private StringBuilder charBuffer = new StringBuilder();
@@ -113,10 +110,6 @@
/** The attributes belonging to the last-started element. */
private Attributes2 lastStartedAttributes;
- /** The last column number that was written. This value is one-based, i.e. after the first character is written on a
- * new line, this value should be 1. */
- private int lastColumnWritten = 0;
-
/* End state variables. */
@@ -127,11 +120,11 @@
* This may be null.
*/
public ForayPrettyPush(final OutputStream output, final String catalog) {
- this.output = output;
this.config = new ForayPrettyConfig();
if (catalog != null) {
this.config.setCatalogs(new String[] {catalog});
}
+ this.queue = new ForayPrettyQueue(this, output);
}
@Override
@@ -138,7 +131,6 @@
public Object parse(final InputSource inputSource) throws IOException, SAXException {
final EntityResolver entityResolver = SaxUtils.getEntityResolver(this.config.getCatalogs());
final XMLReader parser = createSax2Parser(true, true, true, entityResolver, true);
- this.queue = new ForayPrettyQueue(this);
parser.parse(inputSource);
cleanup();
@@ -150,7 +142,7 @@
*/
private void cleanup() {
try {
- this.output.close();
+ this.queue.closeOutput();
} catch (final IOException e1) {
/* Ignore. */
}
@@ -158,13 +150,13 @@
@Override
public void startDocument() {
- write(this.config.getXmlDeclaration());
- write(this.config.getLineTerminator());
+ this.queue.write(this.config.getXmlDeclaration());
+ this.queue.write(this.config.getLineTerminator());
}
@Override
public void endDocument() {
- write(this.config.getLineTerminator());
+ this.queue.write(this.config.getLineTerminator());
}
@Override
@@ -224,7 +216,7 @@
if (qName.equals(this.rootElement)) {
/* Whitespace before and after the end of the root element is
* discarded by SAX, so we need to control it manually. */
- write(this.config.getPreRootText());
+ this.queue.write(this.config.getPreRootText());
}
/* Accumulate the tag opener. */
@@ -257,11 +249,11 @@
/* If starting on new line, write the tag open buffer. */
if (this.startTagOnNewLine()) {
this.queue.flush();
- write(this.config.getLineTerminator());
+ this.queue.write(this.config.getLineTerminator());
if (this.shouldIndent()) {
- write(indent());
+ this.queue.write(indent());
}
- write(tagOpenBuffer.toString());
+ this.queue.write(tagOpenBuffer.toString());
} else {
/* Otherwise queue it up. */
this.queue.add(tagOpenBuffer.toString());
@@ -307,10 +299,10 @@
if (this.topElementWritten) {
if (endTagOnNewLine()) {
this.queue.flush();
- write(this.config.getLineTerminator());
- write(indent());
+ this.queue.write(this.config.getLineTerminator());
+ this.queue.write(indent());
}
- addToQueue("</" + qName + ">");
+ this.queue.add("</" + qName + ">");
if (endTagOnNewLine()) {
this.queue.flush();
}
@@ -321,7 +313,7 @@
if (qName.equals(this.rootElement)) {
/* Whitespace before and after the end of the root element is
* discarded by SAX, so we need to control it manually. */
- write(this.config.getPostRootText());
+ this.queue.write(this.config.getPostRootText());
}
this.elementStack.pop();
}
@@ -370,32 +362,21 @@
}
ensureTopElementWritten(false);
if (this.inCdata) {
- writeRawPCDATA(this.charBuffer.toString());
+ this.queue.writeRawPCDATA(this.charBuffer.toString());
} else if (this.config.isBreakPCDATA()) {
/* Note: SAX input has linefeeds normalized to \n. */
XmlUtils.normalizeWhitespace(this.charBuffer);
this.queue.add(this.charBuffer.toString());
} else {
- writeRawPCDATA(this.charBuffer.toString());
+ this.queue.writeRawPCDATA(this.charBuffer.toString());
}
this.charBuffer.setLength(0);
}
- /**
- * Adds some content to the queue.
- * @param string The content to be added.
- */
- private void addToQueue(final String string) {
- if (string == null) {
- return;
- }
- this.queue.add(string);
- }
-
@Override
public void processingInstruction(final String target, final String data) {
- write(target);
- write(data);
+ this.queue.write(target);
+ this.queue.write(data);
}
@Override
@@ -411,10 +392,10 @@
flushCharacters();
ensureTopElementWritten(false);
this.queue.flush();
- write("<!--");
+ this.queue.write("<!--");
final String comment = new String(buffer, offset, length);
- writeRawPCDATA(comment);
- write("-->");
+ this.queue.writeRawPCDATA(comment);
+ this.queue.write("-->");
}
@Override
@@ -422,7 +403,7 @@
flushCharacters();
ensureTopElementWritten(false);
this.queue.flush();
- writeRawPCDATA("<![CDATA[");
+ this.queue.writeRawPCDATA("<![CDATA[");
this.inCdata = true;
}
@@ -431,32 +412,34 @@
flushCharacters();
ensureTopElementWritten(false);
// this.queue.flush();
- writeRawPCDATA("]]>");
+ this.queue.writeRawPCDATA("]]>");
this.inCdata = false;
}
@Override
public void startDTD(final String name, final String publicId, final String systemId) {
- write(this.config.getLineTerminator());
- write("<!DOCTYPE ");
- write(name);
- write(this.config.getLineTerminator());
+ final StringBuilder builder = new StringBuilder(500);
+ builder.append(this.config.getLineTerminator());
+ builder.append("<!DOCTYPE ");
+ builder.append(name);
+ builder.append(this.config.getLineTerminator());
if (publicId != null
&& ! "".equals(publicId)) {
// Indentation.
- write(" ");
- write("PUBLIC ");
- write("\"" + publicId + "\"");
- write(this.config.getLineTerminator());
+ builder.append(" ");
+ builder.append("PUBLIC ");
+ builder.append("\"" + publicId + "\"");
+ builder.append(this.config.getLineTerminator());
}
// Indentation.
- write(" ");
+ builder.append(" ");
if (publicId == null) {
- write("SYSTEM ");
+ builder.append("SYSTEM ");
}
- write("\"" + systemId + "\"");
- write(">");
- write(this.config.getLineTerminator());
+ builder.append("\"" + systemId + "\"");
+ builder.append(">");
+ builder.append(this.config.getLineTerminator());
+ this.queue.write(builder.toString());
this.inDTD = true;
this.rootElement = name;
}
@@ -488,68 +471,6 @@
}
/**
- * Use this method if the content may contain \n characters that need to be converted to the output line-ending.
- * SAX converts all line-endings, regardless of platform, to \n.
- * Do not use this method for output that has specified line-endings in it, as that may result in the conversion of
- * \r\n to \r\r\n, for example.
- * @param outputString The String that should be written.
- */
- void writeRawPCDATA(final String outputString) {
- if (this.config.getLineTerminator().equals("\n")) {
- /* The specified line terminator is the same as that used in the input. Just write it. */
- write(outputString);
- return;
- }
- final int lastLineBreakIndex = outputString.lastIndexOf("\n");
- if (lastLineBreakIndex < 0) {
- /* No line breaks in what is being written. Just write it. */
- write(outputString);
- return;
- }
- final StringBuilder buffer = new StringBuilder(outputString);
- int bufferIndex = 0;
- while (bufferIndex < buffer.length()) {
- if (buffer.charAt(bufferIndex) == '\n') {
- buffer.replace(bufferIndex, bufferIndex + 1, this.config.getLineTerminator());
- bufferIndex += this.config.getLineTerminator().length();
- } else {
- bufferIndex ++;
- }
- }
- write(buffer.toString());
- }
-
- /**
- * Writes an output String.
- * @param outputString The output to be written.
- */
- void write(final String outputString) {
- if (outputString == null) {
- return;
- }
- if (outputString.length() < 1) {
- return;
- }
- try {
- this.output.write(outputString.getBytes(this.config.getOutputEncoding()));
- /* Following line for debugging only */
- this.output.flush();
- } catch (final IOException e) {
- errorMessage("Error converting text.");
- }
- final int lastLineBreakIndex = outputString.lastIndexOf(this.config.getLineTerminator());
- if (lastLineBreakIndex < 0) {
- /* No line breaks in what is being written. Increment the current
- * column by the length of outputString. Note that we want the
- * count of characters, not bytes, here. */
- this.lastColumnWritten += outputString.length();
- } else {
- this.lastColumnWritten = outputString.length() - lastLineBreakIndex
- - this.config.getLineTerminator().length();
- }
- }
-
- /**
* Compute the current indentation level.
* @return The number of indents for the current state. This is the number of levels that should be indented, not
* necessarily the number of spaces.
@@ -559,14 +480,6 @@
}
/**
- * Returns the last column written.
- * @return the last column written.
- */
- public int getLastColumnWritten() {
- return lastColumnWritten;
- }
-
- /**
* Returns the configuration for this pretty-printer.
* @return The configuration for this pretty-printer.
*/
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyQueue.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyQueue.java 2023-02-04 15:41:37 UTC (rev 13116)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyQueue.java 2023-02-04 16:13:18 UTC (rev 13117)
@@ -28,6 +28,10 @@
package org.foray.xml;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
@@ -39,6 +43,9 @@
/** The pretty-printer to which this queue is attached. */
private ForayPrettyPush pretty;
+ /** The output stream to which the pretty-printed output should be sent. */
+ private OutputStream output;
+
/** Collection of Strings that need to be written as soon as we know enough of what comes after them to choose
* line breaks.
* This is needed for PCDATA and inline tags that must stay on the current line.
@@ -60,12 +67,18 @@
* been chosen. */
private List<Integer> breaksChosen = new ArrayList<Integer>();
+ /** The last column number that was written. This value is one-based, i.e. after the first character is written on a
+ * new line, this value should be 1. */
+ private int lastColumnWritten = 0;
+
/**
* Constructor.
* @param pretty The pretty-printer to which this queue is attached.
+ * @param output The output stream to which the output document should be written.
*/
- public ForayPrettyQueue(final ForayPrettyPush pretty) {
+ public ForayPrettyQueue(final ForayPrettyPush pretty, final OutputStream output) {
this.pretty = pretty;
+ this.output = output;
}
/**
@@ -96,7 +109,7 @@
int sizeIfAccepted = 0;
/* If it is the first item, we must consider what has already been written on the line. */
if (this.breaksChosen.size() < 1) {
- sizeIfAccepted += this.pretty.getLastColumnWritten();
+ sizeIfAccepted += this.lastColumnWritten;
}
final int firstChunkToConsider = this.getLastBreakChosen();
sizeIfAccepted += this.chunkSize(firstChunkToConsider, i);
@@ -119,7 +132,7 @@
*/
private boolean attemptWriteAll() {
/* If they all fit on the current line, write them all. */
- if (charCount() + this.pretty.getLastColumnWritten() <= this.pretty.getConfig().getDesiredLineLength()) {
+ if (charCount() + this.lastColumnWritten <= this.pretty.getConfig().getDesiredLineLength()) {
writeAll();
return true;
}
@@ -132,7 +145,7 @@
private void writeAll() {
while (this.toWriteQueue.size() > 0) {
final String returnItem = this.toWriteQueue.get(0);
- this.pretty.writeRawPCDATA(returnItem);
+ writeRawPCDATA(returnItem);
this.toWriteQueue.remove(0);
}
reset();
@@ -153,6 +166,9 @@
* @param itemToAdd The item to be added to the queue.
*/
protected void add(final String itemToAdd) {
+ if (itemToAdd == null) {
+ return;
+ }
this.toWriteQueue.add(itemToAdd);
}
@@ -373,7 +389,7 @@
/* If the first character on a line is a space, don't write
* it. */
if (string.charAt(startIndex) == ' '
- && this.pretty.getLastColumnWritten() == 0) {
+ && this.lastColumnWritten == 0) {
startIndex ++;
}
}
@@ -387,11 +403,11 @@
if (startIndex > -1
&& endIndex > -1) {
final String stringToWrite = string.substring(startIndex, endIndex + 1);
- this.pretty.write(stringToWrite);
+ write(stringToWrite);
}
}
if (newLine) {
- this.pretty.write(this.pretty.getConfig().getLineTerminator());
+ write(this.pretty.getConfig().getLineTerminator());
}
}
@@ -406,4 +422,75 @@
final int lastIndex = this.toWriteQueue.size() - 1;
return this.toWriteQueue.get(lastIndex);
}
+
+ /**
+ * Closes the output stream.
+ * @throws IOException For errors closing output stream.
+ */
+ void closeOutput() throws IOException {
+ this.output.close();
+ }
+
+ /**
+ * Use this method if the content may contain \n characters that need to be converted to the output line-ending.
+ * SAX converts all line-endings, regardless of platform, to \n.
+ * Do not use this method for output that has specified line-endings in it, as that may result in the conversion of
+ * \r\n to \r\r\n, for example.
+ * @param outputString The String that should be written.
+ */
+ void writeRawPCDATA(final String outputString) {
+ if (this.pretty.getConfig().getLineTerminator().equals("\n")) {
+ /* The specified line terminator is the same as that used in the input. Just write it. */
+ write(outputString);
+ return;
+ }
+ final int lastLineBreakIndex = outputString.lastIndexOf("\n");
+ if (lastLineBreakIndex < 0) {
+ /* No line breaks in what is being written. Just write it. */
+ write(outputString);
+ return;
+ }
+ final StringBuilder buffer = new StringBuilder(outputString);
+ int bufferIndex = 0;
+ while (bufferIndex < buffer.length()) {
+ if (buffer.charAt(bufferIndex) == '\n') {
+ buffer.replace(bufferIndex, bufferIndex + 1, this.pretty.getConfig().getLineTerminator());
+ bufferIndex += this.pretty.getConfig().getLineTerminator().length();
+ } else {
+ bufferIndex ++;
+ }
+ }
+ write(buffer.toString());
+ }
+
+ /**
+ * Writes an output String.
+ * @param outputString The output to be written.
+ */
+ void write(final String outputString) {
+ if (outputString == null) {
+ return;
+ }
+ if (outputString.length() < 1) {
+ return;
+ }
+ try {
+ this.output.write(outputString.getBytes(this.pretty.getConfig().getOutputEncoding()));
+ /* Following line for debugging only */
+ this.output.flush();
+ } catch (final IOException e) {
+ LoggerFactory.getLogger(this.getClass()).error("Error converting text.");
+ }
+ final int lastLineBreakIndex = outputString.lastIndexOf(this.pretty.getConfig().getLineTerminator());
+ if (lastLineBreakIndex < 0) {
+ /* No line breaks in what is being written. Increment the current
+ * column by the length of outputString. Note that we want the
+ * count of characters, not bytes, here. */
+ this.lastColumnWritten += outputString.length();
+ } else {
+ this.lastColumnWritten = outputString.length() - lastLineBreakIndex
+ - this.pretty.getConfig().getLineTerminator().length();
+ }
+ }
+
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-02-04 15:41:41
|
Revision: 13116
http://sourceforge.net/p/foray/code/13116
Author: victormote
Date: 2023-02-04 15:41:37 +0000 (Sat, 04 Feb 2023)
Log Message:
-----------
Break out pretty-print queue for reuse.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java
Added Paths:
-----------
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyQueue.java
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java 2023-02-04 15:17:53 UTC (rev 13115)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java 2023-02-04 15:41:37 UTC (rev 13116)
@@ -57,8 +57,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
@@ -93,7 +91,7 @@
private ElementStack elementStack = new ElementStack();
/** A queue of unprocessed elements. */
- private Queue queue = new Queue();
+ private ForayPrettyQueue queue;
/* Begin state variables. */
@@ -140,6 +138,7 @@
public Object parse(final InputSource inputSource) throws IOException, SAXException {
final EntityResolver entityResolver = SaxUtils.getEntityResolver(this.config.getCatalogs());
final XMLReader parser = createSax2Parser(true, true, true, entityResolver, true);
+ this.queue = new ForayPrettyQueue(this);
parser.parse(inputSource);
cleanup();
@@ -160,12 +159,12 @@
@Override
public void startDocument() {
write(this.config.getXmlDeclaration());
- write(newLine());
+ write(this.config.getLineTerminator());
}
@Override
public void endDocument() {
- write(newLine());
+ write(this.config.getLineTerminator());
}
@Override
@@ -258,7 +257,7 @@
/* If starting on new line, write the tag open buffer. */
if (this.startTagOnNewLine()) {
this.queue.flush();
- write(newLine());
+ write(this.config.getLineTerminator());
if (this.shouldIndent()) {
write(indent());
}
@@ -288,14 +287,6 @@
}
/**
- * Returns what should be written at the end of a line.
- * @return The String content that should be written at the end of a line.
- */
- private String newLine() {
- return this.config.getLineTerminator();
- }
-
- /**
* Returns what should be written to indent a line.
* @return The String content that should be written to indent a line.
*/
@@ -316,7 +307,7 @@
if (this.topElementWritten) {
if (endTagOnNewLine()) {
this.queue.flush();
- write(newLine());
+ write(this.config.getLineTerminator());
write(indent());
}
addToQueue("</" + qName + ">");
@@ -446,10 +437,10 @@
@Override
public void startDTD(final String name, final String publicId, final String systemId) {
- write(newLine());
+ write(this.config.getLineTerminator());
write("<!DOCTYPE ");
write(name);
- write(newLine());
+ write(this.config.getLineTerminator());
if (publicId != null
&& ! "".equals(publicId)) {
// Indentation.
@@ -456,7 +447,7 @@
write(" ");
write("PUBLIC ");
write("\"" + publicId + "\"");
- write(newLine());
+ write(this.config.getLineTerminator());
}
// Indentation.
write(" ");
@@ -465,7 +456,7 @@
}
write("\"" + systemId + "\"");
write(">");
- write(newLine());
+ write(this.config.getLineTerminator());
this.inDTD = true;
this.rootElement = name;
}
@@ -503,7 +494,7 @@
* \r\n to \r\r\n, for example.
* @param outputString The String that should be written.
*/
- private void writeRawPCDATA(final String outputString) {
+ void writeRawPCDATA(final String outputString) {
if (this.config.getLineTerminator().equals("\n")) {
/* The specified line terminator is the same as that used in the input. Just write it. */
write(outputString);
@@ -532,7 +523,7 @@
* Writes an output String.
* @param outputString The output to be written.
*/
- private void write(final String outputString) {
+ void write(final String outputString) {
if (outputString == null) {
return;
}
@@ -568,378 +559,19 @@
}
/**
- * Private inner class for the queue of unprocessed document pieces.
+ * Returns the last column written.
+ * @return the last column written.
*/
- private class Queue {
+ public int getLastColumnWritten() {
+ return lastColumnWritten;
+ }
- /** Collection of Strings that need to be written as soon as we know enough of what comes after them to choose
- * line breaks.
- * This is needed for PCDATA and inline tags that must stay on the current line.
- * It is tempting to turn this all into one long {@link StringBuilder}, but we need to handle attributes
- * differently from PCDATA. */
- private List<String> toWriteQueue = new ArrayList<String>();
-
- /** After running listBreakOpportunities, this array, along with {@link #breakOpportunityIndexes}, holds a list
- * of break opportunities.
- * This array contains a list of items in toWriteQueue. */
- private int[] breakOpportunityItems;
-
- /** After running listBreakOpportunities, this array, along with {@link #breakOpportunityItems}, holds a list of
- * break opportunities.
- * This array points to a specific character in the "items" array. */
- private int[] breakOpportunityIndexes;
-
- /** List of Integer indexes into the breakOpportunity arrays that indicate which opportunities have actually
- * been chosen. */
- private List<Integer> breaksChosen = new ArrayList<Integer>();
-
- /**
- * Constructor.
- */
- Queue() {
- }
-
- /**
- * Flushes all items out of the queue by writing them.
- */
- private void flush() {
- if (attemptWriteAll()) {
- return;
- }
- this.listBreakOpportunities();
- this.chooseBreaks();
- this.writeChosenChunks();
- this.reset();
- }
-
- /**
- * Computes the places in the queue where line breaks should occur.
- */
- private void chooseBreaks() {
- this.breaksChosen.clear();
-
- if (this.breakOpportunityIndexes.length < 1) {
- return;
- }
-
- /* Loop one extra time to catch the last chunk. */
- for (int i = 0; i <= this.breakOpportunityIndexes.length; i++) {
- int sizeIfAccepted = 0;
- /* If it is the first item, we must consider what has already been written on the line. */
- if (this.breaksChosen.size() < 1) {
- sizeIfAccepted += ForayPrettyPush.this.lastColumnWritten;
- }
- final int firstChunkToConsider = this.getLastBreakChosen();
- sizeIfAccepted += this.chunkSize(firstChunkToConsider, i);
- if (sizeIfAccepted > ForayPrettyPush.this.config.getDesiredLineLength()) {
- int breakSelected = i - 1;
- if (breakSelected <= this.getLastBreakChosen()) {
- /* Don't let the same break get chosen again. If the content is too long, we still need to write
- * it once. */
- breakSelected = this.getLastBreakChosen() + 1;
- }
- this.breaksChosen.add(breakSelected);
- }
- }
- }
-
- /**
- * If everything can be written on the current line, do it.
- * Otherwise, do nothing.
- * @return True if everything was written, false otherwise.
- */
- private boolean attemptWriteAll() {
- /* If they all fit on the current line, write them all. */
- if (charCount() + ForayPrettyPush.this.lastColumnWritten <=
- ForayPrettyPush.this.config.getDesiredLineLength()) {
- writeAll();
- return true;
- }
- return false;
- }
-
- /**
- * Writes all items in the queue.
- */
- private void writeAll() {
- while (this.toWriteQueue.size() > 0) {
- final String returnItem = this.toWriteQueue.get(0);
- writeRawPCDATA(returnItem);
- this.toWriteQueue.remove(0);
- }
- reset();
- }
-
- /**
- * Resets the queue to an empty state.
- */
- private void reset() {
- this.breakOpportunityItems = null;
- this.breakOpportunityIndexes = null;
- this.toWriteQueue.clear();
- this.breaksChosen.clear();
- }
-
- /**
- * Adds an item to the queue.
- * @param itemToAdd The item to be added to the queue.
- */
- protected void add(final String itemToAdd) {
- this.toWriteQueue.add(itemToAdd);
- }
-
- /**
- * Returns a specific item from the queue.
- * @param index The index of the item to be returned.
- * @return The specified item.
- */
- protected String get(final int index) {
- if (index > this.toWriteQueue.size()) {
- return null;
- }
- return this.toWriteQueue.get(index);
- }
-
- /**
- * Returns the number of characters to be written from the queue.
- * @return The number of characters to be written from the queue.
- */
- private int charCount() {
- int charCount = 0;
- for (int i = 0; i < this.toWriteQueue.size(); i++) {
- final String string = get(i);
- charCount += string.length();
- }
- return charCount;
- }
-
- /**
- * For all chunks that have been selected, writes them.
- */
- private void writeChosenChunks() {
- /* If there are no breaks, there is nothing to do but write the
- * whole thing.*/
- if (this.breaksChosen.size() < 0) {
- this.writeAll();
- return;
- }
-
- for (int i = 0; i < this.breaksChosen.size(); i++) {
- this.writeChunk(i, true);
- }
- /* Write the last chunk. Don't write a new-line after it. That will
- * be controlled at a higher level. */
- this.writeChunk(Integer.MAX_VALUE, false);
- }
-
- /**
- * Returns the value for a specific chosen item.
- * @param index The index to the chosen break.
- * @return The break value.
- */
- private int getBreakChosen(final int index) {
- if (this.breaksChosen == null
- || index < 0
- || index >= this.breaksChosen.size()) {
- return -1;
- }
- final Object object = this.breaksChosen.get(index);
- final Integer integer = (Integer) object;
- return integer.intValue();
- }
-
- /**
- * Returns the value for the last break chosen.
- * @return The value for the last break chosen.
- */
- private int getLastBreakChosen() {
- final int lastIndex = this.breaksChosen.size() - 1;
- return getBreakChosen(lastIndex);
- }
-
- /**
- * Computes the break opportunies, caching them in member variables.
- */
- private void listBreakOpportunities() {
- int count = countBreakOpportunities();
- this.breakOpportunityItems = new int[count];
- this.breakOpportunityIndexes = new int[count];
- if (count == 0) {
- return;
- }
- count = 0;
- for (int i = 0; i < this.toWriteQueue.size(); i++) {
- final String string = this.get(i);
- for (int j = 0; j < string.length(); j++) {
- final char c = string.charAt(j);
- if (c == ' ') {
- this.breakOpportunityItems[count] = i;
- this.breakOpportunityIndexes[count] = j;
- count ++;
- }
- }
- }
- count = this.breakOpportunityItems.length;
- }
-
- /**
- * Computes the size of a chunk.
- * @param startOpportunity The starting break opportunity.
- * @param endOpportunity The ending break opportunity.
- * @return The size, in chars, of the chunk delimited.
- */
- private int chunkSize(final int startOpportunity,
- final int endOpportunity) {
- if (startOpportunity == endOpportunity) {
- return 0;
- }
- final int startItem;
- final int startItemIndex;
- final int endItem;
- final int endItemIndex;
- if (startOpportunity < 0) {
- startItem = 0;
- startItemIndex = -1;
- } else {
- startItem = this.breakOpportunityItems[startOpportunity];
- startItemIndex = this.breakOpportunityIndexes[startOpportunity];
- }
- final int lastOpportunity = this.breakOpportunityItems.length - 1;
- if (endOpportunity > lastOpportunity) {
- endItem = this.toWriteQueue.size() - 1;
- final String string = this.get(endItem);
- endItemIndex = string.length();
- } else {
- endItem = this.breakOpportunityItems[endOpportunity];
- endItemIndex = this.breakOpportunityIndexes[endOpportunity];
- }
- int size = 0;
- for (int i = startItem; i <= endItem; i++) {
- int startIndex = 0;
- int endIndex = 0;
- if (i == startItem) {
- startIndex = startItemIndex;
- }
- if (i == endItem) {
- endIndex = endItemIndex - 1;
- } else {
- final String item = this.get(i);
- endIndex = item.length() - 1;
- }
- size += endIndex - startIndex;
- if (i != startItem) {
- /* For all but the first item, we must add the space that
- * separates the chunks in order to get the complete size.*/
- size ++;
- }
- }
- return size;
- }
-
- /**
- * Returns the number of break opportunities.
- * @return The number of break opportunities.
- */
- private int countBreakOpportunities() {
- int count = 0;
- for (int i = 0; i < this.toWriteQueue.size(); i++) {
- final String string = this.get(i);
- for (int j = 0; j < string.length(); j++) {
- final char c = string.charAt(j);
- if (c == ' ') {
- count ++;
- }
- }
- }
- return count;
- }
-
- /**
- * Write one of the chunks selected.
- * @param breakSelected The break selection that should be written.
- * @param newLine Set to true if a new-line should be written after the text of the line.
- */
- private void writeChunk(final int breakSelected, final boolean newLine) {
- final int startOpportunity;
- final int endOpportunity;
- if (breakSelected == 0) {
- startOpportunity = Integer.MIN_VALUE;
- endOpportunity = this.getBreakChosen(breakSelected);
- } else if (breakSelected > this.breaksChosen.size() - 1) {
- startOpportunity = this.getLastBreakChosen();
- endOpportunity = Integer.MAX_VALUE;
- } else {
- startOpportunity = this.getBreakChosen(breakSelected - 1);
- endOpportunity = this.getBreakChosen(breakSelected);
- }
-
- final int startItem;
- final int startItemIndex;
- final int endItem;
- final int endItemIndex;
- if (startOpportunity < 0) {
- startItem = 0;
- startItemIndex = 0;
- } else {
- startItem = this.breakOpportunityItems[startOpportunity];
- startItemIndex = this.breakOpportunityIndexes[startOpportunity];
- }
- if (endOpportunity >= this.breakOpportunityIndexes.length) {
- final int lastItem = this.toWriteQueue.size() - 1;
- endItem = lastItem;
- final String lastString = this.getLastItem();
- if (lastString == null) {
- endItemIndex = -1;
- } else {
- endItemIndex = lastString.length() - 1;
- }
- } else {
- endItem = this.breakOpportunityItems[endOpportunity];
- endItemIndex = this.breakOpportunityIndexes[endOpportunity];
- }
- for (int i = startItem; i <= endItem; i++) {
- final String string = this.get(i);
- int startIndex = 0;
- if (i == startItem) {
- startIndex = startItemIndex;
- /* If the first character on a line is a space, don't write
- * it. */
- if (string.charAt(startIndex) == ' '
- && ForayPrettyPush.this.lastColumnWritten == 0) {
- startIndex ++;
- }
- }
- int endIndex = string.length() - 1;
- if (i == endItem) {
- endIndex = endItemIndex;
- if (string.charAt(endIndex) == ' ') {
- endIndex --;
- }
- }
- if (startIndex > -1
- && endIndex > -1) {
- final String stringToWrite = string.substring(startIndex, endIndex + 1);
- write(stringToWrite);
- }
- }
- if (newLine) {
- write(newLine());
- }
- }
-
- /**
- * Returns the last item from the queue.
- * @return The last item from the queue.
- */
- private String getLastItem() {
- if (this.toWriteQueue.size() < 1) {
- return null;
- }
- final int lastIndex = this.toWriteQueue.size() - 1;
- return this.toWriteQueue.get(lastIndex);
- }
-
- /* End of inner class "Queue". */
+ /**
+ * Returns the configuration for this pretty-printer.
+ * @return The configuration for this pretty-printer.
+ */
+ public ForayPrettyConfig getConfig() {
+ return this.config;
}
@Override
Added: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyQueue.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyQueue.java (rev 0)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyQueue.java 2023-02-04 15:41:37 UTC (rev 13116)
@@ -0,0 +1,409 @@
+/*
+ * Copyright 2023 The FOray Project.
+ * http://www.foray.org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This work is in part derived from the following work(s), used with the
+ * permission of the licensor:
+ * Apache FOP, licensed by the Apache Software Foundation
+ *
+ */
+
+/*
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ * $LastChangedBy$
+ */
+
+package org.foray.xml;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The queue of unprocessed document pieces during pretty-printing.
+ */
+public class ForayPrettyQueue {
+
+ /** The pretty-printer to which this queue is attached. */
+ private ForayPrettyPush pretty;
+
+ /** Collection of Strings that need to be written as soon as we know enough of what comes after them to choose
+ * line breaks.
+ * This is needed for PCDATA and inline tags that must stay on the current line.
+ * It is tempting to turn this all into one long {@link StringBuilder}, but we need to handle attributes
+ * differently from PCDATA. */
+ private List<String> toWriteQueue = new ArrayList<String>();
+
+ /** After running listBreakOpportunities, this array, along with {@link #breakOpportunityIndexes}, holds a list
+ * of break opportunities.
+ * This array contains a list of items in toWriteQueue. */
+ private int[] breakOpportunityItems;
+
+ /** After running listBreakOpportunities, this array, along with {@link #breakOpportunityItems}, holds a list of
+ * break opportunities.
+ * This array points to a specific character in the "items" array. */
+ private int[] breakOpportunityIndexes;
+
+ /** List of Integer indexes into the breakOpportunity arrays that indicate which opportunities have actually
+ * been chosen. */
+ private List<Integer> breaksChosen = new ArrayList<Integer>();
+
+ /**
+ * Constructor.
+ * @param pretty The pretty-printer to which this queue is attached.
+ */
+ public ForayPrettyQueue(final ForayPrettyPush pretty) {
+ this.pretty = pretty;
+ }
+
+ /**
+ * Flushes all items out of the queue by writing them.
+ */
+ void flush() {
+ if (attemptWriteAll()) {
+ return;
+ }
+ this.listBreakOpportunities();
+ this.chooseBreaks();
+ this.writeChosenChunks();
+ this.reset();
+ }
+
+ /**
+ * Computes the places in the queue where line breaks should occur.
+ */
+ private void chooseBreaks() {
+ this.breaksChosen.clear();
+
+ if (this.breakOpportunityIndexes.length < 1) {
+ return;
+ }
+
+ /* Loop one extra time to catch the last chunk. */
+ for (int i = 0; i <= this.breakOpportunityIndexes.length; i++) {
+ int sizeIfAccepted = 0;
+ /* If it is the first item, we must consider what has already been written on the line. */
+ if (this.breaksChosen.size() < 1) {
+ sizeIfAccepted += this.pretty.getLastColumnWritten();
+ }
+ final int firstChunkToConsider = this.getLastBreakChosen();
+ sizeIfAccepted += this.chunkSize(firstChunkToConsider, i);
+ if (sizeIfAccepted > this.pretty.getConfig().getDesiredLineLength()) {
+ int breakSelected = i - 1;
+ if (breakSelected <= this.getLastBreakChosen()) {
+ /* Don't let the same break get chosen again. If the content is too long, we still need to write
+ * it once. */
+ breakSelected = this.getLastBreakChosen() + 1;
+ }
+ this.breaksChosen.add(breakSelected);
+ }
+ }
+ }
+
+ /**
+ * If everything can be written on the current line, do it.
+ * Otherwise, do nothing.
+ * @return True if everything was written, false otherwise.
+ */
+ private boolean attemptWriteAll() {
+ /* If they all fit on the current line, write them all. */
+ if (charCount() + this.pretty.getLastColumnWritten() <= this.pretty.getConfig().getDesiredLineLength()) {
+ writeAll();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Writes all items in the queue.
+ */
+ private void writeAll() {
+ while (this.toWriteQueue.size() > 0) {
+ final String returnItem = this.toWriteQueue.get(0);
+ this.pretty.writeRawPCDATA(returnItem);
+ this.toWriteQueue.remove(0);
+ }
+ reset();
+ }
+
+ /**
+ * Resets the queue to an empty state.
+ */
+ private void reset() {
+ this.breakOpportunityItems = null;
+ this.breakOpportunityIndexes = null;
+ this.toWriteQueue.clear();
+ this.breaksChosen.clear();
+ }
+
+ /**
+ * Adds an item to the queue.
+ * @param itemToAdd The item to be added to the queue.
+ */
+ protected void add(final String itemToAdd) {
+ this.toWriteQueue.add(itemToAdd);
+ }
+
+ /**
+ * Returns a specific item from the queue.
+ * @param index The index of the item to be returned.
+ * @return The specified item.
+ */
+ protected String get(final int index) {
+ if (index > this.toWriteQueue.size()) {
+ return null;
+ }
+ return this.toWriteQueue.get(index);
+ }
+
+ /**
+ * Returns the number of characters to be written from the queue.
+ * @return The number of characters to be written from the queue.
+ */
+ private int charCount() {
+ int charCount = 0;
+ for (int i = 0; i < this.toWriteQueue.size(); i++) {
+ final String string = get(i);
+ charCount += string.length();
+ }
+ return charCount;
+ }
+
+ /**
+ * For all chunks that have been selected, writes them.
+ */
+ private void writeChosenChunks() {
+ /* If there are no breaks, there is nothing to do but write the
+ * whole thing.*/
+ if (this.breaksChosen.size() < 0) {
+ this.writeAll();
+ return;
+ }
+
+ for (int i = 0; i < this.breaksChosen.size(); i++) {
+ this.writeChunk(i, true);
+ }
+ /* Write the last chunk. Don't write a new-line after it. That will
+ * be controlled at a higher level. */
+ this.writeChunk(Integer.MAX_VALUE, false);
+ }
+
+ /**
+ * Returns the value for a specific chosen item.
+ * @param index The index to the chosen break.
+ * @return The break value.
+ */
+ private int getBreakChosen(final int index) {
+ if (this.breaksChosen == null
+ || index < 0
+ || index >= this.breaksChosen.size()) {
+ return -1;
+ }
+ final Object object = this.breaksChosen.get(index);
+ final Integer integer = (Integer) object;
+ return integer.intValue();
+ }
+
+ /**
+ * Returns the value for the last break chosen.
+ * @return The value for the last break chosen.
+ */
+ private int getLastBreakChosen() {
+ final int lastIndex = this.breaksChosen.size() - 1;
+ return getBreakChosen(lastIndex);
+ }
+
+ /**
+ * Computes the break opportunies, caching them in member variables.
+ */
+ private void listBreakOpportunities() {
+ int count = countBreakOpportunities();
+ this.breakOpportunityItems = new int[count];
+ this.breakOpportunityIndexes = new int[count];
+ if (count == 0) {
+ return;
+ }
+ count = 0;
+ for (int i = 0; i < this.toWriteQueue.size(); i++) {
+ final String string = this.get(i);
+ for (int j = 0; j < string.length(); j++) {
+ final char c = string.charAt(j);
+ if (c == ' ') {
+ this.breakOpportunityItems[count] = i;
+ this.breakOpportunityIndexes[count] = j;
+ count ++;
+ }
+ }
+ }
+ count = this.breakOpportunityItems.length;
+ }
+
+ /**
+ * Computes the size of a chunk.
+ * @param startOpportunity The starting break opportunity.
+ * @param endOpportunity The ending break opportunity.
+ * @return The size, in chars, of the chunk delimited.
+ */
+ private int chunkSize(final int startOpportunity,
+ final int endOpportunity) {
+ if (startOpportunity == endOpportunity) {
+ return 0;
+ }
+ final int startItem;
+ final int startItemIndex;
+ final int endItem;
+ final int endItemIndex;
+ if (startOpportunity < 0) {
+ startItem = 0;
+ startItemIndex = -1;
+ } else {
+ startItem = this.breakOpportunityItems[startOpportunity];
+ startItemIndex = this.breakOpportunityIndexes[startOpportunity];
+ }
+ final int lastOpportunity = this.breakOpportunityItems.length - 1;
+ if (endOpportunity > lastOpportunity) {
+ endItem = this.toWriteQueue.size() - 1;
+ final String string = this.get(endItem);
+ endItemIndex = string.length();
+ } else {
+ endItem = this.breakOpportunityItems[endOpportunity];
+ endItemIndex = this.breakOpportunityIndexes[endOpportunity];
+ }
+ int size = 0;
+ for (int i = startItem; i <= endItem; i++) {
+ int startIndex = 0;
+ int endIndex = 0;
+ if (i == startItem) {
+ startIndex = startItemIndex;
+ }
+ if (i == endItem) {
+ endIndex = endItemIndex - 1;
+ } else {
+ final String item = this.get(i);
+ endIndex = item.length() - 1;
+ }
+ size += endIndex - startIndex;
+ if (i != startItem) {
+ /* For all but the first item, we must add the space that
+ * separates the chunks in order to get the complete size.*/
+ size ++;
+ }
+ }
+ return size;
+ }
+
+ /**
+ * Returns the number of break opportunities.
+ * @return The number of break opportunities.
+ */
+ private int countBreakOpportunities() {
+ int count = 0;
+ for (int i = 0; i < this.toWriteQueue.size(); i++) {
+ final String string = this.get(i);
+ for (int j = 0; j < string.length(); j++) {
+ final char c = string.charAt(j);
+ if (c == ' ') {
+ count ++;
+ }
+ }
+ }
+ return count;
+ }
+
+ /**
+ * Write one of the chunks selected.
+ * @param breakSelected The break selection that should be written.
+ * @param newLine Set to true if a new-line should be written after the text of the line.
+ */
+ private void writeChunk(final int breakSelected, final boolean newLine) {
+ final int startOpportunity;
+ final int endOpportunity;
+ if (breakSelected == 0) {
+ startOpportunity = Integer.MIN_VALUE;
+ endOpportunity = this.getBreakChosen(breakSelected);
+ } else if (breakSelected > this.breaksChosen.size() - 1) {
+ startOpportunity = this.getLastBreakChosen();
+ endOpportunity = Integer.MAX_VALUE;
+ } else {
+ startOpportunity = this.getBreakChosen(breakSelected - 1);
+ endOpportunity = this.getBreakChosen(breakSelected);
+ }
+
+ final int startItem;
+ final int startItemIndex;
+ final int endItem;
+ final int endItemIndex;
+ if (startOpportunity < 0) {
+ startItem = 0;
+ startItemIndex = 0;
+ } else {
+ startItem = this.breakOpportunityItems[startOpportunity];
+ startItemIndex = this.breakOpportunityIndexes[startOpportunity];
+ }
+ if (endOpportunity >= this.breakOpportunityIndexes.length) {
+ final int lastItem = this.toWriteQueue.size() - 1;
+ endItem = lastItem;
+ final String lastString = this.getLastItem();
+ if (lastString == null) {
+ endItemIndex = -1;
+ } else {
+ endItemIndex = lastString.length() - 1;
+ }
+ } else {
+ endItem = this.breakOpportunityItems[endOpportunity];
+ endItemIndex = this.breakOpportunityIndexes[endOpportunity];
+ }
+ for (int i = startItem; i <= endItem; i++) {
+ final String string = this.get(i);
+ int startIndex = 0;
+ if (i == startItem) {
+ startIndex = startItemIndex;
+ /* If the first character on a line is a space, don't write
+ * it. */
+ if (string.charAt(startIndex) == ' '
+ && this.pretty.getLastColumnWritten() == 0) {
+ startIndex ++;
+ }
+ }
+ int endIndex = string.length() - 1;
+ if (i == endItem) {
+ endIndex = endItemIndex;
+ if (string.charAt(endIndex) == ' ') {
+ endIndex --;
+ }
+ }
+ if (startIndex > -1
+ && endIndex > -1) {
+ final String stringToWrite = string.substring(startIndex, endIndex + 1);
+ this.pretty.write(stringToWrite);
+ }
+ }
+ if (newLine) {
+ this.pretty.write(this.pretty.getConfig().getLineTerminator());
+ }
+ }
+
+ /**
+ * Returns the last item from the queue.
+ * @return The last item from the queue.
+ */
+ private String getLastItem() {
+ if (this.toWriteQueue.size() < 1) {
+ return null;
+ }
+ final int lastIndex = this.toWriteQueue.size() - 1;
+ return this.toWriteQueue.get(lastIndex);
+ }
+}
Property changes on: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyQueue.java
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Rev
\ No newline at end of property
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-02-04 15:17:58
|
Revision: 13115
http://sourceforge.net/p/foray/code/13115
Author: victormote
Date: 2023-02-04 15:17:53 +0000 (Sat, 04 Feb 2023)
Log Message:
-----------
Break pretty-print config into a separate class, for reuse.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java
Added Paths:
-----------
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyConfig.java
Added: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyConfig.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyConfig.java (rev 0)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyConfig.java 2023-02-04 15:17:53 UTC (rev 13115)
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2023 The FOray Project.
+ * http://www.foray.org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This work is in part derived from the following work(s), used with the
+ * permission of the licensor:
+ * Apache FOP, licensed by the Apache Software Foundation
+ *
+ */
+
+/*
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ * $LastChangedBy$
+ */
+
+package org.foray.xml;
+
+import org.foray.primitive.StringUtils;
+
+/**
+ * Configuration options for pretty-printing.
+ */
+public class ForayPrettyConfig {
+
+ /** The default line length that should be used in the pretty-printed output. */
+ private static final byte DEFAULT_LINE_LENGTH = 80;
+
+ /** The encoding to use for the pretty-printed output. */
+ private String outputEncoding = "UTF-8";
+
+ /** The XML declaration string. */
+ private String xmlDeclaration = "<?xml version=\"1.0\" encoding=\"" + this.outputEncoding + "\"?>";
+
+ /** The line terminator that should be used in the output. */
+ private String lineTerminator = System.getProperty("line.separator");
+
+ /** The text that should be output before the root element. */
+ private String preRootText = StringUtils.EMPTY_STRING;
+
+ /** The text that should be output after the root element. */
+ private String postRootText = lineTerminator;
+
+ /** Set this to true if PCDATA content can have space characters replaced by line terminators and vice versa. */
+ private boolean breakPCDATA = true;
+
+ /** The number of spaces that should be indented for each level. */
+ private int indent = 2;
+
+ /** The maximum number of characters desired on each line. */
+ private int desiredLineLength = DEFAULT_LINE_LENGTH;
+
+ /**
+ * Block elements are started on a new line.
+ * However, if they are inside elements containing mixed content, the default behavior is to start the element at
+ * column 0.
+ * If it should be indented, set this variable to true.
+ */
+ private boolean indentBlocksInsideMixedContent = false;
+
+ /** The location of catalogs to use during parsing. */
+ private String[] catalogs;
+
+ /**
+ * Returns the output encoding string.
+ * @return The outputEncoding.
+ */
+ public String getOutputEncoding() {
+ return outputEncoding;
+ }
+
+ /**
+ * Use this configuration parameter to set the output encoding for the pretty-printed document.
+ * The default value is "UTF-8".
+ * @param outputEncoding The new value.
+ */
+ public void setOutputEncoding(final String outputEncoding) {
+ this.outputEncoding = outputEncoding;
+ }
+
+ /**
+ * Returns the XML declaration.
+ * @return The xmlDeclaration.
+ */
+ public String getXmlDeclaration() {
+ return xmlDeclaration;
+ }
+
+ /**
+ * Use this configuration parameter to set the value of the XML Declaration at the beginning of the pretty-printed
+ * document.
+ * The default value is {@code <?xml version="1.0" encoding="UTF-8">}.
+ * @param xmlDeclaration The new value.
+ */
+ public void setXmlDeclaration(final String xmlDeclaration) {
+ this.xmlDeclaration = xmlDeclaration;
+ }
+
+ /**
+ * Returns the line terminator.
+ * @return The line terminator.
+ */
+ public String getLineTerminator() {
+ return lineTerminator;
+ }
+
+ /**
+ * Use this configuration parameter to set the text that should be used to delimit lines in the pretty-printed
+ * document.
+ * The default is platform-specific.
+ * On Unix, for example, it is "\n".
+ * On Windows, it is "\r\n".
+ * @param lineTerminator The new value.
+ */
+ public void setLineTerminator(final String lineTerminator) {
+ this.lineTerminator = lineTerminator;
+ }
+
+ /**
+ * Returns the pre-root text.
+ * @return The pre-root text.
+ */
+ public String getPreRootText() {
+ return preRootText;
+ }
+
+ /**
+ * Use this configuration parameter to control the text that is written right before the root element.
+ * Any text between the Dtd and the root element in the source document is considered to be insignificant and is
+ * therefore stripped out.
+ * The default value is null.
+ * @param preRootText The new value.
+ */
+ public void setPreRootText(final String preRootText) {
+ this.preRootText = preRootText;
+ }
+
+ /**
+ * Returns the post-root text.
+ * @return the post-root text.
+ */
+ public String getPostRootText() {
+ return postRootText;
+ }
+
+ /**
+ * Use this configuration parameter to control the text that is written right after the close of the root element.
+ * Any text after the root element in the source document is considered to be insignificant and is therefore
+ * stripped out.
+ * The default value is "\n" (one line-feed).
+ * @param postRootText The new value.
+ */
+ public void setPostRootText(final String postRootText) {
+ this.postRootText = postRootText;
+ }
+
+ /**
+ * Returns the break PCDATA.
+ * @return The break PCDATA.
+ */
+ public boolean isBreakPCDATA() {
+ return breakPCDATA;
+ }
+
+ /**
+ * Set this configuration parameter to true if whitespace within PCDATA can be interchanged.
+ * Specifically, if this parameter is set, tabs will be normalized to spaces, duplicate spaces will be removed, and
+ * spaces and new-lines will be treated as interchangeable.
+ * The default value is true.
+ * @param breakPCDATA The new value.
+ */
+ public void setBreakPCDATA(final boolean breakPCDATA) {
+ this.breakPCDATA = breakPCDATA;
+ }
+
+ /**
+ * Returns the indent.
+ * @return The indent.
+ */
+ public int getIndent() {
+ return indent;
+ }
+
+ /**
+ * Use this configuration parameter to set the number of spaces that each successive block level of the document
+ * should be indented.
+ * The default is 2.
+ * @param indent The new value.
+ */
+ public void setIndent(final int indent) {
+ this.indent = indent;
+ }
+
+ /**
+ * Returns the desired line length.
+ * @return The desired line length.
+ */
+ public int getDesiredLineLength() {
+ return desiredLineLength;
+ }
+
+ /**
+ * Use this configuration parameter to set the desired maximum line length, in characters, for the pretty-printed
+ * document.
+ * The default is 80.
+ * @param desiredLineLength The new value.
+ */
+ public void setDesiredLineLength(final int desiredLineLength) {
+ this.desiredLineLength = desiredLineLength;
+ }
+
+ /**
+ * Returns the indent blocks inside mixed content.
+ * @return The indent blocks inside mixed content.
+ */
+ public boolean isIndentBlocksInsideMixedContent() {
+ return indentBlocksInsideMixedContent;
+ }
+
+ /**
+ * Set this configuration parameter to true if blocks that are inside of mixed content should be indented.
+ * The default is "false".
+ * @param indentBlocksInsideMixedContent The new value.
+ */
+ public void setIndentBlocksInsideMixedContent(final boolean indentBlocksInsideMixedContent) {
+ this.indentBlocksInsideMixedContent = indentBlocksInsideMixedContent;
+ }
+
+ /**
+ * Returns the catalogs.
+ * @return the catalogs.
+ */
+ public String[] getCatalogs() {
+ return catalogs;
+ }
+
+ /**
+ * Sets the catalogs.
+ * @param catalogs The catalogs to set.
+ */
+ public void setCatalogs(final String[] catalogs) {
+ this.catalogs = catalogs;
+ }
+
+}
Property changes on: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyConfig.java
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Rev
\ No newline at end of property
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java 2023-02-04 14:32:07 UTC (rev 13114)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java 2023-02-04 15:17:53 UTC (rev 13115)
@@ -77,8 +77,8 @@
/** Command-line return status constant indicating that there was an error parsing the input file. */
public static final byte STATUS_PARSING_ERROR = 3;
- /** The default line length that should be used in the pretty-printed output. */
- private static final byte DEFAULT_LINE_LENGTH = 80;
+ /** The configuration for this pretty-printer. */
+ private ForayPrettyConfig config;
/** The output stream to which the pretty-printed output should be sent. */
private OutputStream output;
@@ -121,46 +121,8 @@
/* End state variables. */
- /* Begin configuration variables. */
- /** The encoding to use for the pretty-printed output. */
- private String outputEncoding = "UTF-8";
-
- /** The XML declaration string. */
- private String xmlDeclaration = "<?xml version=\"1.0\" encoding=\"" + this.outputEncoding + "\"?>";
-
- /** The line terminator that should be used in the output. */
- private String lineTerminator = "\n";
-
- /** The text that should be output before the root element. */
- private String preRootText = null;
-
- /** The text that should be output after the root element. */
- private String postRootText = "\n";
-
- /** Set this to true if PCDATA content can have space characters replaced by line terminators and vice versa. */
- private boolean breakPCDATA = true;
-
- /** The number of spaces that should be indented for each level. */
- private int indent = 2;
-
- /** The maximum number of characters desired on each line. */
- private int desiredLineLength = ForayPrettyPush.DEFAULT_LINE_LENGTH;
-
/**
- * Block elements are started on a new line.
- * However, if they are inside elements containing mixed content, the default behavior is to start the element at
- * column 0.
- * If it should be indented, set this variable to true.
- */
- private boolean indentBlocksInsideMixedContent = false;
-
- /** The location of catalogs to use during parsing. */
- private String[] catalogs;
-
- /* End configuration variables. */
-
- /**
* Constructor.
* @param output The output stream to which the pretty-printed document should be sent.
* @param catalog The location of a catalog file that should be used to find the Dtd for this document.
@@ -168,20 +130,15 @@
*/
public ForayPrettyPush(final OutputStream output, final String catalog) {
this.output = output;
+ this.config = new ForayPrettyConfig();
if (catalog != null) {
- this.catalogs = new String[] {catalog};
+ this.config.setCatalogs(new String[] {catalog});
}
-
- /* Set the line terminator to the default for this operating system. */
- this.lineTerminator = System.getProperty("line.separator");
- /* Default the pre- and post- root text to one line separator. */
- this.preRootText = null;
- this.postRootText = this.lineTerminator;
}
@Override
public Object parse(final InputSource inputSource) throws IOException, SAXException {
- final EntityResolver entityResolver = SaxUtils.getEntityResolver(catalogs);
+ final EntityResolver entityResolver = SaxUtils.getEntityResolver(this.config.getCatalogs());
final XMLReader parser = createSax2Parser(true, true, true, entityResolver, true);
parser.parse(inputSource);
@@ -202,7 +159,7 @@
@Override
public void startDocument() {
- write(this.xmlDeclaration);
+ write(this.config.getXmlDeclaration());
write(newLine());
}
@@ -268,7 +225,7 @@
if (qName.equals(this.rootElement)) {
/* Whitespace before and after the end of the root element is
* discarded by SAX, so we need to control it manually. */
- write(this.preRootText);
+ write(this.config.getPreRootText());
}
/* Accumulate the tag opener. */
@@ -324,7 +281,7 @@
return false;
}
if (this.elementStack.topIsInsideMixedContent()) {
- return this.indentBlocksInsideMixedContent;
+ return this.config.isIndentBlocksInsideMixedContent();
}
/* It is a block element, not inside mixed content. Indent it. */
return true;
@@ -335,7 +292,7 @@
* @return The String content that should be written at the end of a line.
*/
private String newLine() {
- return this.lineTerminator;
+ return this.config.getLineTerminator();
}
/**
@@ -343,7 +300,7 @@
* @return The String content that should be written to indent a line.
*/
private String indent() {
- int numIndents = currentIndentation() * this.indent;
+ int numIndents = currentIndentation() * this.config.getIndent();
final StringBuilder buffer = new StringBuilder();
while (numIndents > 0) {
buffer.append(" ");
@@ -373,7 +330,7 @@
if (qName.equals(this.rootElement)) {
/* Whitespace before and after the end of the root element is
* discarded by SAX, so we need to control it manually. */
- write(this.postRootText);
+ write(this.config.getPostRootText());
}
this.elementStack.pop();
}
@@ -423,7 +380,7 @@
ensureTopElementWritten(false);
if (this.inCdata) {
writeRawPCDATA(this.charBuffer.toString());
- } else if (this.breakPCDATA) {
+ } else if (this.config.isBreakPCDATA()) {
/* Note: SAX input has linefeeds normalized to \n. */
XmlUtils.normalizeWhitespace(this.charBuffer);
this.queue.add(this.charBuffer.toString());
@@ -547,7 +504,7 @@
* @param outputString The String that should be written.
*/
private void writeRawPCDATA(final String outputString) {
- if (this.lineTerminator.equals("\n")) {
+ if (this.config.getLineTerminator().equals("\n")) {
/* The specified line terminator is the same as that used in the input. Just write it. */
write(outputString);
return;
@@ -562,8 +519,8 @@
int bufferIndex = 0;
while (bufferIndex < buffer.length()) {
if (buffer.charAt(bufferIndex) == '\n') {
- buffer.replace(bufferIndex, bufferIndex + 1, this.lineTerminator);
- bufferIndex += this.lineTerminator.length();
+ buffer.replace(bufferIndex, bufferIndex + 1, this.config.getLineTerminator());
+ bufferIndex += this.config.getLineTerminator().length();
} else {
bufferIndex ++;
}
@@ -583,13 +540,13 @@
return;
}
try {
- this.output.write(outputString.getBytes(this.outputEncoding));
+ this.output.write(outputString.getBytes(this.config.getOutputEncoding()));
/* Following line for debugging only */
this.output.flush();
} catch (final IOException e) {
errorMessage("Error converting text.");
}
- final int lastLineBreakIndex = outputString.lastIndexOf(this.lineTerminator);
+ final int lastLineBreakIndex = outputString.lastIndexOf(this.config.getLineTerminator());
if (lastLineBreakIndex < 0) {
/* No line breaks in what is being written. Increment the current
* column by the length of outputString. Note that we want the
@@ -596,7 +553,8 @@
* count of characters, not bytes, here. */
this.lastColumnWritten += outputString.length();
} else {
- this.lastColumnWritten = outputString.length() - lastLineBreakIndex - this.lineTerminator.length();
+ this.lastColumnWritten = outputString.length() - lastLineBreakIndex
+ - this.config.getLineTerminator().length();
}
}
@@ -673,7 +631,7 @@
}
final int firstChunkToConsider = this.getLastBreakChosen();
sizeIfAccepted += this.chunkSize(firstChunkToConsider, i);
- if (sizeIfAccepted > ForayPrettyPush.this.desiredLineLength) {
+ if (sizeIfAccepted > ForayPrettyPush.this.config.getDesiredLineLength()) {
int breakSelected = i - 1;
if (breakSelected <= this.getLastBreakChosen()) {
/* Don't let the same break get chosen again. If the content is too long, we still need to write
@@ -692,7 +650,8 @@
*/
private boolean attemptWriteAll() {
/* If they all fit on the current line, write them all. */
- if (charCount() + ForayPrettyPush.this.lastColumnWritten <= ForayPrettyPush.this.desiredLineLength) {
+ if (charCount() + ForayPrettyPush.this.lastColumnWritten <=
+ ForayPrettyPush.this.config.getDesiredLineLength()) {
writeAll();
return true;
}
@@ -983,99 +942,6 @@
/* End of inner class "Queue". */
}
- /**
- * Set this configuration parameter to true if whitespace within PCDATA can be interchanged.
- * Specifically, if this parameter is set, tabs will be normalized to spaces, duplicate spaces will be removed, and
- * spaces and new-lines will be treated as interchangeable.
- * The default value is true.
- * @param breakPCDATA The new value.
- */
- public void setBreakPCDATA(final boolean breakPCDATA) {
- this.breakPCDATA = breakPCDATA;
- }
-
- /**
- * Use this configuration parameter to set the value of the XML Declaration at the beginning of the pretty-printed
- * document.
- * The default value is {@code <?xml version="1.0" encoding="UTF-8">}.
- * @param xmlDeclaration The new value.
- */
- public void setXmlDeclaration(final String xmlDeclaration) {
- this.xmlDeclaration = xmlDeclaration;
- }
-
- /**
- * Use this configuration parameter to set the text that should be used to delimit lines in the pretty-printed
- * document.
- * The default is platform-specific.
- * On Unix, for example, it is "\n".
- * On Windows, it is "\r\n".
- * @param lineTerminator The new value.
- */
- public void setLineTerminator(final String lineTerminator) {
- this.lineTerminator = lineTerminator;
- }
-
- /**
- * Use this configuration parameter to set the output encoding for the pretty-printed document.
- * The default value is "UTF-8".
- * @param outputEncoding The new value.
- */
- public void setOutputEncoding(final String outputEncoding) {
- this.outputEncoding = outputEncoding;
- }
-
- /**
- * Use this configuration parameter to control the text that is written right before the root element.
- * Any text between the Dtd and the root element in the source document is considered to be insignificant and is
- * therefore stripped out.
- * The default value is null.
- * @param preRootText The new value.
- */
- public void setPreRootText(final String preRootText) {
- this.preRootText = preRootText;
- }
-
- /**
- * Use this configuration parameter to control the text that is written right after the close of the root element.
- * Any text after the root element in the source document is considered to be insignificant and is therefore
- * stripped out.
- * The default value is "\n" (one line-feed).
- * @param postRootText The new value.
- */
- public void setPostRootText(final String postRootText) {
- this.postRootText = postRootText;
- }
-
- /**
- * Use this configuration parameter to set the number of spaces that each successive block level of the document
- * should be indented.
- * The default is 2.
- * @param indent The new value.
- */
- public void setIndent(final int indent) {
- this.indent = indent;
- }
-
- /**
- * Use this configuration parameter to set the desired maximum line length, in characters, for the pretty-printed
- * document.
- * The default is 80.
- * @param desiredLineLength The new value.
- */
- public void setDesiredLineLength(final int desiredLineLength) {
- this.desiredLineLength = desiredLineLength;
- }
-
- /**
- * Set this configuration parameter to true if blocks that are inside of mixed content should be indented.
- * The default is "false".
- * @param indent The new value.
- */
- public void setIndentBlocksInsideMixedContent(final boolean indent) {
- this.indentBlocksInsideMixedContent = indent;
- }
-
@Override
public void reset() {
throw new UnsupportedOperationException();
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-02-04 14:32:12
|
Revision: 13114
http://sourceforge.net/p/foray/code/13114
Author: victormote
Date: 2023-02-04 14:32:07 +0000 (Sat, 04 Feb 2023)
Log Message:
-----------
Rename class in preparation for a variant of it.
Added Paths:
-----------
trunk/foray/foray-00-master/ide/eclipse/launch-configurations/xml-ForayPrettyPush.launch
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java
Removed Paths:
-------------
trunk/foray/foray-00-master/ide/eclipse/launch-configurations/xml-ForayPretty.launch
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java
Deleted: trunk/foray/foray-00-master/ide/eclipse/launch-configurations/xml-ForayPretty.launch
===================================================================
--- trunk/foray/foray-00-master/ide/eclipse/launch-configurations/xml-ForayPretty.launch 2023-02-04 14:05:54 UTC (rev 13113)
+++ trunk/foray/foray-00-master/ide/eclipse/launch-configurations/xml-ForayPretty.launch 2023-02-04 14:32:07 UTC (rev 13114)
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
- <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
- <listEntry value="/foray-xml/src/main/java/org/foray/xml/ForayPretty.java"/>
- </listAttribute>
- <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
- <listEntry value="1"/>
- </listAttribute>
- <booleanAttribute key="org.eclipse.jdt.launching.ATTR_EXCLUDE_TEST_CODE" value="true"/>
- <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_CLASSPATH_ONLY_JAR" value="false"/>
- <listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
- <listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/" javaProject="foray-xml" path="1" type="4"/> "/>
- <listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry id="org.eclipse.jdt.launching.classpathentry.defaultClasspath"> <memento exportedEntriesOnly="false" project="foray-xml"/> </runtimeClasspathEntry> "/>
- <listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.USER_LIBRARY/logback" path="3" type="4"/> "/>
- </listAttribute>
- <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
- <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.foray.xml.ForayPretty"/>
- <stringAttribute key="org.eclipse.jdt.launching.MODULE_NAME" value="foray-xml"/>
- <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="--input ${foray-test-input-dir}/pretty-print-input.xml --output ${foray-test-output-dir}/pretty-print-output.xml --catalog ${foray-catalog-file}"/>
- <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="foray-xml"/>
-</launchConfiguration>
Added: trunk/foray/foray-00-master/ide/eclipse/launch-configurations/xml-ForayPrettyPush.launch
===================================================================
--- trunk/foray/foray-00-master/ide/eclipse/launch-configurations/xml-ForayPrettyPush.launch (rev 0)
+++ trunk/foray/foray-00-master/ide/eclipse/launch-configurations/xml-ForayPrettyPush.launch 2023-02-04 14:32:07 UTC (rev 13114)
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
+ <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+ <listEntry value="/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java"/>
+ </listAttribute>
+ <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+ <listEntry value="1"/>
+ </listAttribute>
+ <booleanAttribute key="org.eclipse.jdt.launching.ATTR_EXCLUDE_TEST_CODE" value="true"/>
+ <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_CLASSPATH_ONLY_JAR" value="false"/>
+ <listAttribute key="org.eclipse.jdt.launching.CLASSPATH">
+ <listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/" javaProject="foray-xml" path="1" type="4"/> "/>
+ <listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry id="org.eclipse.jdt.launching.classpathentry.defaultClasspath"> <memento exportedEntriesOnly="false" project="foray-xml"/> </runtimeClasspathEntry> "/>
+ <listEntry value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <runtimeClasspathEntry containerPath="org.eclipse.jdt.USER_LIBRARY/logback" path="3" type="4"/> "/>
+ </listAttribute>
+ <booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
+ <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.foray.xml.ForayPrettyPush"/>
+ <stringAttribute key="org.eclipse.jdt.launching.MODULE_NAME" value="foray-xml"/>
+ <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="--input ${foray-test-input-dir}/pretty-print-input.xml --output ${foray-test-output-dir}/pretty-print-output.xml --catalog ${foray-catalog-file}"/>
+ <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="foray-xml"/>
+</launchConfiguration>
Property changes on: trunk/foray/foray-00-master/ide/eclipse/launch-configurations/xml-ForayPrettyPush.launch
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Rev
\ No newline at end of property
Deleted: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java 2023-02-04 14:05:54 UTC (rev 13113)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java 2023-02-04 14:32:07 UTC (rev 13114)
@@ -1,1174 +0,0 @@
-/*
- * Copyright 2005 The FOray Project.
- * http://www.foray.org
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * This work is in part derived from the following work(s), used with the
- * permission of the licensor:
- * Apache FOP, licensed by the Apache Software Foundation
- *
- */
-
-/*
- * $LastChangedRevision$
- * $LastChangedDate$
- * $LastChangedBy$
- */
-
-package org.foray.xml;
-
-import org.foray.xml.dtd.ElementStack;
-import org.foray.xml.model.XsdElement;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
-import org.apache.commons.cli.DefaultParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-import org.apache.ws.commons.schema.XmlSchemaElement;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xml.sax.Attributes;
-import org.xml.sax.EntityResolver;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-import org.xml.sax.ext.Attributes2;
-import org.xml.sax.ext.Attributes2Impl;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import javax.xml.namespace.QName;
-
-/**
- * Reads an XML file and writes a pretty-printed version of it.
- */
-public class ForayPretty extends SaxParser<Object> {
-
- /** Command-line status constant indicating that the command line itself was not properly formed. */
- public static final byte STATUS_COMMAND_LINE_ERROR = 1;
-
- /** Command-line return status constant indicating that a file was not found. */
- public static final byte STATUS_FILE_NOT_FOUND = 2;
-
- /** Command-line return status constant indicating that there was an error parsing the input file. */
- public static final byte STATUS_PARSING_ERROR = 3;
-
- /** The default line length that should be used in the pretty-printed output. */
- private static final byte DEFAULT_LINE_LENGTH = 80;
-
- /** The output stream to which the pretty-printed output should be sent. */
- private OutputStream output;
-
- /** A reusable buffer. */
- private StringBuilder charBuffer = new StringBuilder();
-
- /** The name of the root element of this document. */
- private String rootElement;
-
- /** The element stack. */
- private ElementStack elementStack = new ElementStack();
-
- /** A queue of unprocessed elements. */
- private Queue queue = new Queue();
-
- /* Begin state variables. */
-
- /** State variable tracking whether we are currently inside the Dtd or not. */
- private boolean inDTD = false;
-
- /** State variable tracking whether we are currently inside an entity expansion or not. */
- private boolean inEntityReference = false;
-
- /** State variable tracking whether we are currently inside a CDATA section or not. */
- private boolean inCdata = false;
-
- /** Indicates whether the item on the top of the element stack has been written. */
- private boolean topElementWritten = true;
-
- /** The name of the last started-element. */
- private String lastStartedElement;
-
- /** The attributes belonging to the last-started element. */
- private Attributes2 lastStartedAttributes;
-
- /** The last column number that was written. This value is one-based, i.e. after the first character is written on a
- * new line, this value should be 1. */
- private int lastColumnWritten = 0;
-
- /* End state variables. */
-
- /* Begin configuration variables. */
-
- /** The encoding to use for the pretty-printed output. */
- private String outputEncoding = "UTF-8";
-
- /** The XML declaration string. */
- private String xmlDeclaration = "<?xml version=\"1.0\" encoding=\"" + this.outputEncoding + "\"?>";
-
- /** The line terminator that should be used in the output. */
- private String lineTerminator = "\n";
-
- /** The text that should be output before the root element. */
- private String preRootText = null;
-
- /** The text that should be output after the root element. */
- private String postRootText = "\n";
-
- /** Set this to true if PCDATA content can have space characters replaced by line terminators and vice versa. */
- private boolean breakPCDATA = true;
-
- /** The number of spaces that should be indented for each level. */
- private int indent = 2;
-
- /** The maximum number of characters desired on each line. */
- private int desiredLineLength = ForayPretty.DEFAULT_LINE_LENGTH;
-
- /**
- * Block elements are started on a new line.
- * However, if they are inside elements containing mixed content, the default behavior is to start the element at
- * column 0.
- * If it should be indented, set this variable to true.
- */
- private boolean indentBlocksInsideMixedContent = false;
-
- /** The location of catalogs to use during parsing. */
- private String[] catalogs;
-
- /* End configuration variables. */
-
- /**
- * Constructor.
- * @param output The output stream to which the pretty-printed document should be sent.
- * @param catalog The location of a catalog file that should be used to find the Dtd for this document.
- * This may be null.
- */
- public ForayPretty(final OutputStream output, final String catalog) {
- this.output = output;
- if (catalog != null) {
- this.catalogs = new String[] {catalog};
- }
-
- /* Set the line terminator to the default for this operating system. */
- this.lineTerminator = System.getProperty("line.separator");
- /* Default the pre- and post- root text to one line separator. */
- this.preRootText = null;
- this.postRootText = this.lineTerminator;
- }
-
- @Override
- public Object parse(final InputSource inputSource) throws IOException, SAXException {
- final EntityResolver entityResolver = SaxUtils.getEntityResolver(catalogs);
- final XMLReader parser = createSax2Parser(true, true, true, entityResolver, true);
-
- parser.parse(inputSource);
- cleanup();
- return null;
- }
-
- /**
- * Finalize the processing.
- */
- private void cleanup() {
- try {
- this.output.close();
- } catch (final IOException e1) {
- /* Ignore. */
- }
- }
-
- @Override
- public void startDocument() {
- write(this.xmlDeclaration);
- write(newLine());
- }
-
- @Override
- public void endDocument() {
- write(newLine());
- }
-
- @Override
- public void startElement(final String uri, final String local, final String qName, final Attributes attributes)
- throws SAXException {
- flushCharacters();
- ensureTopElementWritten(false);
- parseSchemaLocation(attributes);
-
-
-
- /* Cache the parameters in instance variable for later processing.
- * We don't want to write the element yet, because the next event received might be the close of the same
- * element, and empty elements can be written two different ways.*/
- this.lastStartedElement = qName;
- /* Must copy the attributes as they are reset on each callback. */
- this.lastStartedAttributes = new Attributes2Impl(attributes);
- if (getDtd() == null) {
- final QName qname = new QName(uri, local);
- final XmlSchemaElement schemaElement = getSchemaElement(qname);
-
- final Map<XmlSchemaElement, XsdElement> schemaElementMap = getSchemaElementMap();
- XsdElement xsdElement = schemaElementMap.get(schemaElement);
- if (xsdElement == null) {
- xsdElement = new XsdElement(schemaElement);
- schemaElementMap.put(schemaElement, xsdElement);
- }
- this.elementStack.push(xsdElement);
- } else {
- this.elementStack.push(getDtd().getElement(qName));
- }
- this.topElementWritten = false;
- }
-
- /**
- * Writes the element at the top of the stack if it has not already been written.
- * @param isEmpty Indicates whether the element has any content or not.
- */
- private void ensureTopElementWritten(final boolean isEmpty) {
- if (this.topElementWritten) {
- return;
- }
- writeElement(this.lastStartedElement, this.lastStartedAttributes, isEmpty);
- this.topElementWritten = true;
- }
-
- /**
- * Writes an element.
- * @param qName The namespace-qualified name of the element to be written.
- * @param attributes The attributes for the element to be written.
- * @param isEmpty Indicates whether the element has any content or not.
- */
- private void writeElement(final String qName, final Attributes2 attributes, final boolean isEmpty) {
- if (qName == null) {
- return;
- }
- if (qName.equals(this.rootElement)) {
- /* Whitespace before and after the end of the root element is
- * discarded by SAX, so we need to control it manually. */
- write(this.preRootText);
- }
-
- /* Accumulate the tag opener. */
- final StringBuilder tagOpenBuffer = new StringBuilder();
- tagOpenBuffer.append("<");
- tagOpenBuffer.append(qName);
-
- /* Accumulate the attributes. */
- final StringBuilder attributesBuffer = new StringBuilder();
- for (int i = 0; i < attributes.getLength(); i++) {
- /* Check "isSpecified" to eliminate any attributes that were included by the parser as a default, in other
- * words, attributes that did not actually exist in the parsed text. */
- if (attributes.isSpecified(i)) {
- attributesBuffer.append(" ");
- attributesBuffer.append(attributes.getQName(i));
- attributesBuffer.append("=\"");
- attributesBuffer.append(attributes.getValue(i));
- attributesBuffer.append("\"");
- }
- }
-
- /* Accumulate the tag closer. */
- final StringBuilder tagCloseBuffer = new StringBuilder();
- if (isEmpty) {
- tagCloseBuffer.append("/>");
- } else {
- tagCloseBuffer.append(">");
- }
-
- /* If starting on new line, write the tag open buffer. */
- if (this.startTagOnNewLine()) {
- this.queue.flush();
- write(newLine());
- if (this.shouldIndent()) {
- write(indent());
- }
- write(tagOpenBuffer.toString());
- } else {
- /* Otherwise queue it up. */
- this.queue.add(tagOpenBuffer.toString());
- }
-
- /* Queue up the attributes and tag close. */
- this.queue.add(attributesBuffer.toString() + tagCloseBuffer.toString());
- }
-
- /**
- * Indicates whether the top element in the stack should be indented.
- * @return True if and only if the top element in the stack should be indented.
- */
- private boolean shouldIndent() {
- if (! this.elementStack.topIsBlockElement()) {
- return false;
- }
- if (this.elementStack.topIsInsideMixedContent()) {
- return this.indentBlocksInsideMixedContent;
- }
- /* It is a block element, not inside mixed content. Indent it. */
- return true;
- }
-
- /**
- * Returns what should be written at the end of a line.
- * @return The String content that should be written at the end of a line.
- */
- private String newLine() {
- return this.lineTerminator;
- }
-
- /**
- * Returns what should be written to indent a line.
- * @return The String content that should be written to indent a line.
- */
- private String indent() {
- int numIndents = currentIndentation() * this.indent;
- final StringBuilder buffer = new StringBuilder();
- while (numIndents > 0) {
- buffer.append(" ");
- numIndents --;
- }
- return buffer.toString();
- }
-
- @Override
- public void endElement(final String uri, final String local, final String qName) {
- flushCharacters();
-
- if (this.topElementWritten) {
- if (endTagOnNewLine()) {
- this.queue.flush();
- write(newLine());
- write(indent());
- }
- addToQueue("</" + qName + ">");
- if (endTagOnNewLine()) {
- this.queue.flush();
- }
- } else {
- /* Element was empty. */
- ensureTopElementWritten(true);
- }
- if (qName.equals(this.rootElement)) {
- /* Whitespace before and after the end of the root element is
- * discarded by SAX, so we need to control it manually. */
- write(this.postRootText);
- }
- this.elementStack.pop();
- }
-
- /**
- * Determines whether the start tag for the current element should be written on a new line or whether it should be
- * written inside the parent tag.
- * @return True if the start tag for the current element should be written on a new line.
- */
- private boolean startTagOnNewLine() {
- return this.elementStack.topIsBlockElement();
- }
-
- /**
- * Determines whether the end tag for the current element should be written on a new line or whether it should be
- * written immediately after the contents.
- * @return True if the end tag for the current element should be written on a new line.
- */
- private boolean endTagOnNewLine() {
- if (! this.elementStack.topIsBlockElement()) {
- return false;
- }
- /* If the current element contains PCDATA, the end tag should be written in-line instead of on a new line. */
- if (this.elementStack.topHasPCDATA()) {
- return false;
- }
- return true;
- }
-
- @Override
- public void characters(final char[] buffer, final int offset, final int length) {
- if (this.inEntityReference) {
- /* Skip these characters. We are writing the unexpanded entity elsewhere. We do not want to also write the
- * expanded version. */
- return;
- }
- this.charBuffer.append(buffer, offset, length);
- }
-
- /**
- * Pushes any character in the buffer into the queue to be written.
- */
- private void flushCharacters() {
- if (this.charBuffer.length() < 1) {
- return;
- }
- ensureTopElementWritten(false);
- if (this.inCdata) {
- writeRawPCDATA(this.charBuffer.toString());
- } else if (this.breakPCDATA) {
- /* Note: SAX input has linefeeds normalized to \n. */
- XmlUtils.normalizeWhitespace(this.charBuffer);
- this.queue.add(this.charBuffer.toString());
- } else {
- writeRawPCDATA(this.charBuffer.toString());
- }
- this.charBuffer.setLength(0);
- }
-
- /**
- * Adds some content to the queue.
- * @param string The content to be added.
- */
- private void addToQueue(final String string) {
- if (string == null) {
- return;
- }
- this.queue.add(string);
- }
-
- @Override
- public void processingInstruction(final String target, final String data) {
- write(target);
- write(data);
- }
-
- @Override
- public void ignorableWhitespace(final char[] buffer, final int offset, final int length) {
- /* Ignorable white space is just ignored. */
- }
-
- @Override
- public void comment(final char[] buffer, final int offset, final int length) {
- if (this.inDTD) {
- return;
- }
- flushCharacters();
- ensureTopElementWritten(false);
- this.queue.flush();
- write("<!--");
- final String comment = new String(buffer, offset, length);
- writeRawPCDATA(comment);
- write("-->");
- }
-
- @Override
- public void startCDATA() throws SAXException {
- flushCharacters();
- ensureTopElementWritten(false);
- this.queue.flush();
- writeRawPCDATA("<![CDATA[");
- this.inCdata = true;
- }
-
- @Override
- public void endCDATA() throws SAXException {
- flushCharacters();
- ensureTopElementWritten(false);
-// this.queue.flush();
- writeRawPCDATA("]]>");
- this.inCdata = false;
- }
-
- @Override
- public void startDTD(final String name, final String publicId, final String systemId) {
- write(newLine());
- write("<!DOCTYPE ");
- write(name);
- write(newLine());
- if (publicId != null
- && ! "".equals(publicId)) {
- // Indentation.
- write(" ");
- write("PUBLIC ");
- write("\"" + publicId + "\"");
- write(newLine());
- }
- // Indentation.
- write(" ");
- if (publicId == null) {
- write("SYSTEM ");
- }
- write("\"" + systemId + "\"");
- write(">");
- write(newLine());
- this.inDTD = true;
- this.rootElement = name;
- }
-
- @Override
- public void endDTD() {
- this.inDTD = false;
- }
-
- @Override
- public void startEntity(final String name) {
- if (this.inDTD) {
- return;
- }
- /* General entity references have their "&" prefix stripped off, so we must add it back. Parameters entity
- * references have their "%" prefix left intact. */
- if (name.charAt(0) != '%') {
- this.charBuffer.append("&");
- }
- this.charBuffer.append(name);
- this.charBuffer.append(";");
-
- this.inEntityReference = true;
- }
-
- @Override
- public void endEntity(final String name) {
- this.inEntityReference = false;
- }
-
- /**
- * Use this method if the content may contain \n characters that need to be converted to the output line-ending.
- * SAX converts all line-endings, regardless of platform, to \n.
- * Do not use this method for output that has specified line-endings in it, as that may result in the conversion of
- * \r\n to \r\r\n, for example.
- * @param outputString The String that should be written.
- */
- private void writeRawPCDATA(final String outputString) {
- if (this.lineTerminator.equals("\n")) {
- /* The specified line terminator is the same as that used in the input. Just write it. */
- write(outputString);
- return;
- }
- final int lastLineBreakIndex = outputString.lastIndexOf("\n");
- if (lastLineBreakIndex < 0) {
- /* No line breaks in what is being written. Just write it. */
- write(outputString);
- return;
- }
- final StringBuilder buffer = new StringBuilder(outputString);
- int bufferIndex = 0;
- while (bufferIndex < buffer.length()) {
- if (buffer.charAt(bufferIndex) == '\n') {
- buffer.replace(bufferIndex, bufferIndex + 1, this.lineTerminator);
- bufferIndex += this.lineTerminator.length();
- } else {
- bufferIndex ++;
- }
- }
- write(buffer.toString());
- }
-
- /**
- * Writes an output String.
- * @param outputString The output to be written.
- */
- private void write(final String outputString) {
- if (outputString == null) {
- return;
- }
- if (outputString.length() < 1) {
- return;
- }
- try {
- this.output.write(outputString.getBytes(this.outputEncoding));
- /* Following line for debugging only */
- this.output.flush();
- } catch (final IOException e) {
- errorMessage("Error converting text.");
- }
- final int lastLineBreakIndex = outputString.lastIndexOf(this.lineTerminator);
- if (lastLineBreakIndex < 0) {
- /* No line breaks in what is being written. Increment the current
- * column by the length of outputString. Note that we want the
- * count of characters, not bytes, here. */
- this.lastColumnWritten += outputString.length();
- } else {
- this.lastColumnWritten = outputString.length() - lastLineBreakIndex - this.lineTerminator.length();
- }
- }
-
- /**
- * Compute the current indentation level.
- * @return The number of indents for the current state. This is the number of levels that should be indented, not
- * necessarily the number of spaces.
- */
- private int currentIndentation() {
- return this.elementStack.size() - 1;
- }
-
- /**
- * Private inner class for the queue of unprocessed document pieces.
- */
- private class Queue {
-
- /** Collection of Strings that need to be written as soon as we know enough of what comes after them to choose
- * line breaks.
- * This is needed for PCDATA and inline tags that must stay on the current line.
- * It is tempting to turn this all into one long {@link StringBuilder}, but we need to handle attributes
- * differently from PCDATA. */
- private List<String> toWriteQueue = new ArrayList<String>();
-
- /** After running listBreakOpportunities, this array, along with {@link #breakOpportunityIndexes}, holds a list
- * of break opportunities.
- * This array contains a list of items in toWriteQueue. */
- private int[] breakOpportunityItems;
-
- /** After running listBreakOpportunities, this array, along with {@link #breakOpportunityItems}, holds a list of
- * break opportunities.
- * This array points to a specific character in the "items" array. */
- private int[] breakOpportunityIndexes;
-
- /** List of Integer indexes into the breakOpportunity arrays that indicate which opportunities have actually
- * been chosen. */
- private List<Integer> breaksChosen = new ArrayList<Integer>();
-
- /**
- * Constructor.
- */
- Queue() {
- }
-
- /**
- * Flushes all items out of the queue by writing them.
- */
- private void flush() {
- if (attemptWriteAll()) {
- return;
- }
- this.listBreakOpportunities();
- this.chooseBreaks();
- this.writeChosenChunks();
- this.reset();
- }
-
- /**
- * Computes the places in the queue where line breaks should occur.
- */
- private void chooseBreaks() {
- this.breaksChosen.clear();
-
- if (this.breakOpportunityIndexes.length < 1) {
- return;
- }
-
- /* Loop one extra time to catch the last chunk. */
- for (int i = 0; i <= this.breakOpportunityIndexes.length; i++) {
- int sizeIfAccepted = 0;
- /* If it is the first item, we must consider what has already been written on the line. */
- if (this.breaksChosen.size() < 1) {
- sizeIfAccepted += ForayPretty.this.lastColumnWritten;
- }
- final int firstChunkToConsider = this.getLastBreakChosen();
- sizeIfAccepted += this.chunkSize(firstChunkToConsider, i);
- if (sizeIfAccepted > ForayPretty.this.desiredLineLength) {
- int breakSelected = i - 1;
- if (breakSelected <= this.getLastBreakChosen()) {
- /* Don't let the same break get chosen again. If the content is too long, we still need to write
- * it once. */
- breakSelected = this.getLastBreakChosen() + 1;
- }
- this.breaksChosen.add(breakSelected);
- }
- }
- }
-
- /**
- * If everything can be written on the current line, do it.
- * Otherwise, do nothing.
- * @return True if everything was written, false otherwise.
- */
- private boolean attemptWriteAll() {
- /* If they all fit on the current line, write them all. */
- if (charCount() + ForayPretty.this.lastColumnWritten <= ForayPretty.this.desiredLineLength) {
- writeAll();
- return true;
- }
- return false;
- }
-
- /**
- * Writes all items in the queue.
- */
- private void writeAll() {
- while (this.toWriteQueue.size() > 0) {
- final String returnItem = this.toWriteQueue.get(0);
- writeRawPCDATA(returnItem);
- this.toWriteQueue.remove(0);
- }
- reset();
- }
-
- /**
- * Resets the queue to an empty state.
- */
- private void reset() {
- this.breakOpportunityItems = null;
- this.breakOpportunityIndexes = null;
- this.toWriteQueue.clear();
- this.breaksChosen.clear();
- }
-
- /**
- * Adds an item to the queue.
- * @param itemToAdd The item to be added to the queue.
- */
- protected void add(final String itemToAdd) {
- this.toWriteQueue.add(itemToAdd);
- }
-
- /**
- * Returns a specific item from the queue.
- * @param index The index of the item to be returned.
- * @return The specified item.
- */
- protected String get(final int index) {
- if (index > this.toWriteQueue.size()) {
- return null;
- }
- return this.toWriteQueue.get(index);
- }
-
- /**
- * Returns the number of characters to be written from the queue.
- * @return The number of characters to be written from the queue.
- */
- private int charCount() {
- int charCount = 0;
- for (int i = 0; i < this.toWriteQueue.size(); i++) {
- final String string = get(i);
- charCount += string.length();
- }
- return charCount;
- }
-
- /**
- * For all chunks that have been selected, writes them.
- */
- private void writeChosenChunks() {
- /* If there are no breaks, there is nothing to do but write the
- * whole thing.*/
- if (this.breaksChosen.size() < 0) {
- this.writeAll();
- return;
- }
-
- for (int i = 0; i < this.breaksChosen.size(); i++) {
- this.writeChunk(i, true);
- }
- /* Write the last chunk. Don't write a new-line after it. That will
- * be controlled at a higher level. */
- this.writeChunk(Integer.MAX_VALUE, false);
- }
-
- /**
- * Returns the value for a specific chosen item.
- * @param index The index to the chosen break.
- * @return The break value.
- */
- private int getBreakChosen(final int index) {
- if (this.breaksChosen == null
- || index < 0
- || index >= this.breaksChosen.size()) {
- return -1;
- }
- final Object object = this.breaksChosen.get(index);
- final Integer integer = (Integer) object;
- return integer.intValue();
- }
-
- /**
- * Returns the value for the last break chosen.
- * @return The value for the last break chosen.
- */
- private int getLastBreakChosen() {
- final int lastIndex = this.breaksChosen.size() - 1;
- return getBreakChosen(lastIndex);
- }
-
- /**
- * Computes the break opportunies, caching them in member variables.
- */
- private void listBreakOpportunities() {
- int count = countBreakOpportunities();
- this.breakOpportunityItems = new int[count];
- this.breakOpportunityIndexes = new int[count];
- if (count == 0) {
- return;
- }
- count = 0;
- for (int i = 0; i < this.toWriteQueue.size(); i++) {
- final String string = this.get(i);
- for (int j = 0; j < string.length(); j++) {
- final char c = string.charAt(j);
- if (c == ' ') {
- this.breakOpportunityItems[count] = i;
- this.breakOpportunityIndexes[count] = j;
- count ++;
- }
- }
- }
- count = this.breakOpportunityItems.length;
- }
-
- /**
- * Computes the size of a chunk.
- * @param startOpportunity The starting break opportunity.
- * @param endOpportunity The ending break opportunity.
- * @return The size, in chars, of the chunk delimited.
- */
- private int chunkSize(final int startOpportunity,
- final int endOpportunity) {
- if (startOpportunity == endOpportunity) {
- return 0;
- }
- final int startItem;
- final int startItemIndex;
- final int endItem;
- final int endItemIndex;
- if (startOpportunity < 0) {
- startItem = 0;
- startItemIndex = -1;
- } else {
- startItem = this.breakOpportunityItems[startOpportunity];
- startItemIndex = this.breakOpportunityIndexes[startOpportunity];
- }
- final int lastOpportunity = this.breakOpportunityItems.length - 1;
- if (endOpportunity > lastOpportunity) {
- endItem = this.toWriteQueue.size() - 1;
- final String string = this.get(endItem);
- endItemIndex = string.length();
- } else {
- endItem = this.breakOpportunityItems[endOpportunity];
- endItemIndex = this.breakOpportunityIndexes[endOpportunity];
- }
- int size = 0;
- for (int i = startItem; i <= endItem; i++) {
- int startIndex = 0;
- int endIndex = 0;
- if (i == startItem) {
- startIndex = startItemIndex;
- }
- if (i == endItem) {
- endIndex = endItemIndex - 1;
- } else {
- final String item = this.get(i);
- endIndex = item.length() - 1;
- }
- size += endIndex - startIndex;
- if (i != startItem) {
- /* For all but the first item, we must add the space that
- * separates the chunks in order to get the complete size.*/
- size ++;
- }
- }
- return size;
- }
-
- /**
- * Returns the number of break opportunities.
- * @return The number of break opportunities.
- */
- private int countBreakOpportunities() {
- int count = 0;
- for (int i = 0; i < this.toWriteQueue.size(); i++) {
- final String string = this.get(i);
- for (int j = 0; j < string.length(); j++) {
- final char c = string.charAt(j);
- if (c == ' ') {
- count ++;
- }
- }
- }
- return count;
- }
-
- /**
- * Write one of the chunks selected.
- * @param breakSelected The break selection that should be written.
- * @param newLine Set to true if a new-line should be written after the text of the line.
- */
- private void writeChunk(final int breakSelected, final boolean newLine) {
- final int startOpportunity;
- final int endOpportunity;
- if (breakSelected == 0) {
- startOpportunity = Integer.MIN_VALUE;
- endOpportunity = this.getBreakChosen(breakSelected);
- } else if (breakSelected > this.breaksChosen.size() - 1) {
- startOpportunity = this.getLastBreakChosen();
- endOpportunity = Integer.MAX_VALUE;
- } else {
- startOpportunity = this.getBreakChosen(breakSelected - 1);
- endOpportunity = this.getBreakChosen(breakSelected);
- }
-
- final int startItem;
- final int startItemIndex;
- final int endItem;
- final int endItemIndex;
- if (startOpportunity < 0) {
- startItem = 0;
- startItemIndex = 0;
- } else {
- startItem = this.breakOpportunityItems[startOpportunity];
- startItemIndex = this.breakOpportunityIndexes[startOpportunity];
- }
- if (endOpportunity >= this.breakOpportunityIndexes.length) {
- final int lastItem = this.toWriteQueue.size() - 1;
- endItem = lastItem;
- final String lastString = this.getLastItem();
- if (lastString == null) {
- endItemIndex = -1;
- } else {
- endItemIndex = lastString.length() - 1;
- }
- } else {
- endItem = this.breakOpportunityItems[endOpportunity];
- endItemIndex = this.breakOpportunityIndexes[endOpportunity];
- }
- for (int i = startItem; i <= endItem; i++) {
- final String string = this.get(i);
- int startIndex = 0;
- if (i == startItem) {
- startIndex = startItemIndex;
- /* If the first character on a line is a space, don't write
- * it. */
- if (string.charAt(startIndex) == ' '
- && ForayPretty.this.lastColumnWritten == 0) {
- startIndex ++;
- }
- }
- int endIndex = string.length() - 1;
- if (i == endItem) {
- endIndex = endItemIndex;
- if (string.charAt(endIndex) == ' ') {
- endIndex --;
- }
- }
- if (startIndex > -1
- && endIndex > -1) {
- final String stringToWrite = string.substring(startIndex, endIndex + 1);
- write(stringToWrite);
- }
- }
- if (newLine) {
- write(newLine());
- }
- }
-
- /**
- * Returns the last item from the queue.
- * @return The last item from the queue.
- */
- private String getLastItem() {
- if (this.toWriteQueue.size() < 1) {
- return null;
- }
- final int lastIndex = this.toWriteQueue.size() - 1;
- return this.toWriteQueue.get(lastIndex);
- }
-
- /* End of inner class "Queue". */
- }
-
- /**
- * Set this configuration parameter to true if whitespace within PCDATA can be interchanged.
- * Specifically, if this parameter is set, tabs will be normalized to spaces, duplicate spaces will be removed, and
- * spaces and new-lines will be treated as interchangeable.
- * The default value is true.
- * @param breakPCDATA The new value.
- */
- public void setBreakPCDATA(final boolean breakPCDATA) {
- this.breakPCDATA = breakPCDATA;
- }
-
- /**
- * Use this configuration parameter to set the value of the XML Declaration at the beginning of the pretty-printed
- * document.
- * The default value is {@code <?xml version="1.0" encoding="UTF-8">}.
- * @param xmlDeclaration The new value.
- */
- public void setXmlDeclaration(final String xmlDeclaration) {
- this.xmlDeclaration = xmlDeclaration;
- }
-
- /**
- * Use this configuration parameter to set the text that should be used to delimit lines in the pretty-printed
- * document.
- * The default is platform-specific.
- * On Unix, for example, it is "\n".
- * On Windows, it is "\r\n".
- * @param lineTerminator The new value.
- */
- public void setLineTerminator(final String lineTerminator) {
- this.lineTerminator = lineTerminator;
- }
-
- /**
- * Use this configuration parameter to set the output encoding for the pretty-printed document.
- * The default value is "UTF-8".
- * @param outputEncoding The new value.
- */
- public void setOutputEncoding(final String outputEncoding) {
- this.outputEncoding = outputEncoding;
- }
-
- /**
- * Use this configuration parameter to control the text that is written right before the root element.
- * Any text between the Dtd and the root element in the source document is considered to be insignificant and is
- * therefore stripped out.
- * The default value is null.
- * @param preRootText The new value.
- */
- public void setPreRootText(final String preRootText) {
- this.preRootText = preRootText;
- }
-
- /**
- * Use this configuration parameter to control the text that is written right after the close of the root element.
- * Any text after the root element in the source document is considered to be insignificant and is therefore
- * stripped out.
- * The default value is "\n" (one line-feed).
- * @param postRootText The new value.
- */
- public void setPostRootText(final String postRootText) {
- this.postRootText = postRootText;
- }
-
- /**
- * Use this configuration parameter to set the number of spaces that each successive block level of the document
- * should be indented.
- * The default is 2.
- * @param indent The new value.
- */
- public void setIndent(final int indent) {
- this.indent = indent;
- }
-
- /**
- * Use this configuration parameter to set the desired maximum line length, in characters, for the pretty-printed
- * document.
- * The default is 80.
- * @param desiredLineLength The new value.
- */
- public void setDesiredLineLength(final int desiredLineLength) {
- this.desiredLineLength = desiredLineLength;
- }
-
- /**
- * Set this configuration parameter to true if blocks that are inside of mixed content should be indented.
- * The default is "false".
- * @param indent The new value.
- */
- public void setIndentBlocksInsideMixedContent(final boolean indent) {
- this.indentBlocksInsideMixedContent = indent;
- }
-
- @Override
- public void reset() {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Returns the command-line options for the {@link #main(String[])} method.
- * @return Command-line options.
- */
- private static Options getCommandLineOptions() {
- final Options clOptions = new Options();
- final Option input = new Option("i", "input", true, "path to the input file");
- input.setRequired(true);
- final Option output = new Option("o", "output", true, "path to the output (pretty-printed) file");
- output.setRequired(true);
- final Option catalog = new Option("c", "catalog", true, "path to the OASIS XML catalog");
- output.setRequired(true);
- clOptions.addOption(input);
- clOptions.addOption(output);
- clOptions.addOption(catalog);
- return clOptions;
- }
-
- /**
- * Command-line interface for pretty-printing an XML document.
- *
- * <p>Design Note: We use files instead of URLs here to more easily integrate with desktop tools such as XML
- * editors, which typically know how to pass parameters for local files, but not how to convert them to URLs.
- * If URLs are needed, additional flags probably need to be added to the command-line interface to designate
- * that.</p>
- *
- * <p>Return status is one of:</p>
- * <ul>
- * <li>0 (success)</li>
- * <li>1 (wrong quantity of arguments)</li>
- * <li>2 (file not found)</li>
- * <li>3 (parsing error)</li>
- * </ul>
- *
- * @param args command-line arguments.
- * Argument 1 is the location of the input file.
- * Argument 2 is the location of the output file.
- * Argument 3 is an optional location of an OASIS-compliant catalog file that can be used to locate local DTDs.
- */
- public static void main(final String[] args) {
- final Logger logger = LoggerFactory.getLogger(ForayPretty.class);
- final Options commandLineOptions = ForayPretty.getCommandLineOptions();
- final CommandLineParser commandLineParser = new DefaultParser();
- CommandLine parsedCommandLine = null;
- try {
- parsedCommandLine = commandLineParser.parse(commandLineOptions, args);
- } catch (final ParseException e) {
- logger.error(e.getMessage(), e);
- final HelpFormatter helpFormatter = new HelpFormatter();
- helpFormatter.printHelp("java -cp $FORAY_CLASSPATH " + ForayPretty.class.getName(), commandLineOptions,
- true);
- /* CheckStyle: Allow System.exit() in main method. */
- System.exit(ForayPretty.STATUS_COMMAND_LINE_ERROR);
- }
-
- final String input = parsedCommandLine.getOptionValue("input");
- final String output = parsedCommandLine.getOptionValue("output");
- final String catalog = parsedCommandLine.getOptionValue("catalog");
-
- InputStream inputStream = null;
- try {
- FileInputStream fis = null;
- fis = new FileInputStream(input);
- inputStream = new BufferedInputStream(fis);
- } catch (final FileNotFoundException e) {
- logger.error("File cannot be opened for input: " + input, e);
- /* CheckStyle: Allow System.exit() in main method. */
- System.exit(ForayPretty.STATUS_FILE_NOT_FOUND);
- }
- final InputSource inputSource = new InputSource(inputStream);
- OutputStream outputStream = null;
- try {
- final FileOutputStream fos = new FileOutputStream(output);
- outputStream = new BufferedOutputStream(fos);
- } catch (final FileNotFoundException e) {
- logger.error("File cannot be opened for output: " + output, e);
- /* CheckStyle: Allow System.exit() in main method. */
- System.exit(ForayPretty.STATUS_FILE_NOT_FOUND);
- }
- final ForayPretty processor = new ForayPretty(outputStream, catalog);
- try {
- processor.parse(inputSource);
- } catch (final IOException | SAXException e) {
- logger.error("Error parsing " + input, e);
- /* CheckStyle: Allow System.exit() in main method. */
- System.exit(ForayPretty.STATUS_PARSING_ERROR);
- }
- logger.info("Input: " + input + " successfully pretty-printed,\n output in: " + output);
- }
-
-}
Copied: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java (from rev 13113, trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java)
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java (rev 0)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPrettyPush.java 2023-02-04 14:32:07 UTC (rev 13114)
@@ -0,0 +1,1174 @@
+/*
+ * Copyright 2005 The FOray Project.
+ * http://www.foray.org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This work is in part derived from the following work(s), used with the
+ * permission of the licensor:
+ * Apache FOP, licensed by the Apache Software Foundation
+ *
+ */
+
+/*
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ * $LastChangedBy$
+ */
+
+package org.foray.xml;
+
+import org.foray.xml.dtd.ElementStack;
+import org.foray.xml.model.XsdElement;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.ws.commons.schema.XmlSchemaElement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.Attributes2;
+import org.xml.sax.ext.Attributes2Impl;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.QName;
+
+/**
+ * Reads an XML file and writes a pretty-printed version of it.
+ */
+public class ForayPrettyPush extends SaxParser<Object> {
+
+ /** Command-line status constant indicating that the command line itself was not properly formed. */
+ public static final byte STATUS_COMMAND_LINE_ERROR = 1;
+
+ /** Command-line return status constant indicating that a file was not found. */
+ public static final byte STATUS_FILE_NOT_FOUND = 2;
+
+ /** Command-line return status constant indicating that there was an error parsing the input file. */
+ public static final byte STATUS_PARSING_ERROR = 3;
+
+ /** The default line length that should be used in the pretty-printed output. */
+ private static final byte DEFAULT_LINE_LENGTH = 80;
+
+ /** The output stream to which the pretty-printed output should be sent. */
+ private OutputStream output;
+
+ /** A reusable buffer. */
+ private StringBuilder charBuffer = new StringBuilder();
+
+ /** The name of the root element of this document. */
+ private String rootElement;
+
+ /** The element stack. */
+ private ElementStack elementStack = new ElementStack();
+
+ /** A queue of unprocessed elements. */
+ private Queue queue = new Queue();
+
+ /* Begin state variables. */
+
+ /** State variable tracking whether we are currently inside the Dtd or not. */
+ private boolean inDTD = false;
+
+ /** State variable tracking whether we are currently inside an entity expansion or not. */
+ private boolean inEntityReference = false;
+
+ /** State variable tracking whether we are currently inside a CDATA section or not. */
+ private boolean inCdata = false;
+
+ /** Indicates whether the item on the top of the element stack has been written. */
+ private boolean topElementWritten = true;
+
+ /** The name of the last started-element. */
+ private String lastStartedElement;
+
+ /** The attributes belonging to the last-started element. */
+ private Attributes2 lastStartedAttributes;
+
+ /** The last column number that was written. This value is one-based, i.e. after the first character is written on a
+ * new line, this value should be 1. */
+ private int lastColumnWritten = 0;
+
+ /* End state variables. */
+
+ /* Begin configuration variables. */
+
+ /** The encoding to use for the pretty-printed output. */
+ private String outputEncoding = "UTF-8";
+
+ /** The XML declaration string. */
+ private String xmlDeclaration = "<?xml version=\"1.0\" encoding=\"" + this.outputEncoding + "\"?>";
+
+ /** The line terminator that should be used in the output. */
+ private String lineTerminator = "\n";
+
+ /** The text that should be output before the root element. */
+ private String preRootText = null;
+
+ /** The text that should be output after the root element. */
+ private String postRootText = "\n";
+
+ /** Set this to true if PCDATA content can have space characters replaced by line terminators and vice versa. */
+ private boolean breakPCDATA = true;
+
+ /** The number of spaces that should be indented for each level. */
+ private int indent = 2;
+
+ /** The maximum number of characters desired on each line. */
+ private int desiredLineLength = ForayPrettyPush.DEFAULT_LINE_LENGTH;
+
+ /**
+ * Block elements are started on a new line.
+ * However, if they are inside elements containing mixed content, the default behavior is to start the element at
+ * column 0.
+ * If it should be indented, set this variable to true.
+ */
+ private boolean indentBlocksInsideMixedContent = false;
+
+ /** The location of catalogs to use during parsing. */
+ private String[] catalogs;
+
+ /* End configuration variables. */
+
+ /**
+ * Constructor.
+ * @param output The output stream to which the pretty-printed document should be sent.
+ * @param catalog The location of a catalog file that should be used to find the Dtd for this document.
+ * This may be null.
+ */
+ public ForayPrettyPush(final OutputStream output, final String catalog) {
+ this.output = output;
+ if (catalog != null) {
+ this.catalogs = new String[] {catalog};
+ }
+
+ /* Set the line terminator to the default for this operating system. */
+ this.lineTerminator = System.getProperty("line.separator");
+ /* Default the pre- and post- root text to one line separator. */
+ this.preRootText = null;
+ this.postRootText = this.lineTerminator;
+ }
+
+ @Override
+ public Object parse(final InputSource inputSource) throws IOException, SAXException {
+ final EntityResolver entityResolver = SaxUtils.getEntityResolver(catalogs);
+ final XMLReader parser = createSax2Parser(true, true, true, entityResolver, true);
+
+ parser.parse(inputSource);
+ cleanup();
+ return null;
+ }
+
+ /**
+ * Finalize the processing.
+ */
+ private void cleanup() {
+ try {
+ this.output.close();
+ } catch (final IOException e1) {
+ /* Ignore. */
+ }
+ }
+
+ @Override
+ public void startDocument() {
+ write(this.xmlDeclaration);
+ write(newLine());
+ }
+
+ @Override
+ public void endDocument() {
+ write(newLine());
+ }
+
+ @Override
+ public void startElement(final String uri, final String local, final String qName, final Attributes attributes)
+ throws SAXException {
+ flushCharacters();
+ ensureTopElementWritten(false);
+ parseSchemaLocation(attributes);
+
+
+
+ /* Cache the parameters in instance variable for later processing.
+ * We don't want to write the element yet, because the next event received might be the close of the same
+ * element, and empty elements can be written two different ways.*/
+ this.lastStartedElement = qName;
+ /* Must copy the attributes as they are reset on each callback. */
+ this.lastStartedAttributes = new Attributes2Impl(attributes);
+ if (getDtd() == null) {
+ final QName qname = new QName(uri, local);
+ final XmlSchemaElement schemaElement = getSchemaElement(qname);
+
+ final Map<XmlSchemaElement, XsdElement> schemaElementMap = getSchemaElementMap();
+ XsdElement xsdElement = schemaElementMap.get(schemaElement);
+ if (xsdElement == null) {
+ xsdElement = new XsdElement(schemaElement);
+ schemaElementMap.put(schemaElement, xsdElement);
+ }
+ this.elementStack.push(xsdElement);
+ } else {
+ this.elementStack.push(getDtd().getElement(qName));
+ }
+ this.topElementWritten = false;
+ }
+
+ /**
+ * Writes the...
[truncated message content] |
|
From: <vic...@us...> - 2023-02-04 14:05:56
|
Revision: 13113
http://sourceforge.net/p/foray/code/13113
Author: victormote
Date: 2023-02-04 14:05:54 +0000 (Sat, 04 Feb 2023)
Log Message:
-----------
Improvement to parameter entity reference handling.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java 2023-02-04 14:04:55 UTC (rev 13112)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java 2023-02-04 14:05:54 UTC (rev 13113)
@@ -101,7 +101,7 @@
private boolean inDTD = false;
/** State variable tracking whether we are currently inside an entity expansion or not. */
- private boolean inEntity = false;
+ private boolean inEntityReference = false;
/** State variable tracking whether we are currently inside a CDATA section or not. */
private boolean inCdata = false;
@@ -404,9 +404,8 @@
}
@Override
- public void characters(final char[] buffer, final int offset,
- final int length) {
- if (this.inEntity) {
+ public void characters(final char[] buffer, final int offset, final int length) {
+ if (this.inEntityReference) {
/* Skip these characters. We are writing the unexpanded entity elsewhere. We do not want to also write the
* expanded version. */
return;
@@ -524,16 +523,20 @@
if (this.inDTD) {
return;
}
- /* Assumes for now that all are general entities. */
- this.charBuffer.append("&");
+ /* General entity references have their "&" prefix stripped off, so we must add it back. Parameters entity
+ * references have their "%" prefix left intact. */
+ if (name.charAt(0) != '%') {
+ this.charBuffer.append("&");
+ }
this.charBuffer.append(name);
this.charBuffer.append(";");
- this.inEntity = true;
+
+ this.inEntityReference = true;
}
@Override
public void endEntity(final String name) {
- this.inEntity = false;
+ this.inEntityReference = false;
}
/**
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-02-04 14:04:57
|
Revision: 13112
http://sourceforge.net/p/foray/code/13112
Author: victormote
Date: 2023-02-04 14:04:55 +0000 (Sat, 04 Feb 2023)
Log Message:
-----------
Report parameter entity events.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java 2023-02-03 18:24:34 UTC (rev 13111)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java 2023-02-04 14:04:55 UTC (rev 13112)
@@ -241,10 +241,11 @@
/* Standard SAX features and properties. */
+ /* First, make some assertions about read-only settings. */
assertFeature(xmlReader, SaxStdFeatures.USE_ATTRIBUTES2, true, Level.ERROR);
assertFeature(xmlReader, SaxStdFeatures.USE_LOCATOR2, true, Level.ERROR);
-
+ /* Second, adjust settings for writable options. */
setFeature(xmlReader, SaxStdFeatures.NAMESPACES, namespacePrefixes, Level.ERROR);
setFeature(xmlReader, SaxStdFeatures.NAMESPACE_PREFIXES, namespacePrefixes, Level.ERROR);
/* Turn on validation if it is available. */
@@ -251,6 +252,9 @@
if (validate) {
setFeature(xmlReader, SaxStdFeatures.VALIDATION, true, Level.WARN);
}
+ /* Report the beginning and end of parameter entities. */
+ setFeature(xmlReader, SaxStdFeatures.LEXICAL_HANDLER_PARAMETER_ENTITIES, true, Level.ERROR);
+
/* Bind the LexicalHandler to the XMLReader if possible. */
setProperty(xmlReader, SaxStdProperties.LEXICAL_HANDLER, this, Level.ERROR);
/* Bind the DeclHandler to the XMLReader if possible. */
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-02-03 18:24:37
|
Revision: 13111
http://sourceforge.net/p/foray/code/13111
Author: victormote
Date: 2023-02-03 18:24:34 +0000 (Fri, 03 Feb 2023)
Log Message:
-----------
Move SAX property assertion to superclass. Add another there.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java
trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java 2023-02-03 13:39:56 UTC (rev 13110)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java 2023-02-03 18:24:34 UTC (rev 13111)
@@ -41,7 +41,6 @@
import org.apache.ws.commons.schema.XmlSchemaElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.slf4j.event.Level;
import org.xml.sax.Attributes;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
@@ -185,8 +184,6 @@
final EntityResolver entityResolver = SaxUtils.getEntityResolver(catalogs);
final XMLReader parser = createSax2Parser(true, true, true, entityResolver, true);
- assertFeature(parser, SaxStdFeatures.USE_ATTRIBUTES2, true, Level.ERROR);
-
parser.parse(inputSource);
cleanup();
return null;
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java 2023-02-03 13:39:56 UTC (rev 13110)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java 2023-02-03 18:24:34 UTC (rev 13111)
@@ -49,6 +49,7 @@
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.DefaultHandler2;
+import org.xml.sax.ext.Locator2;
import org.xml.sax.helpers.XMLReaderFactory;
import java.io.IOException;
@@ -101,7 +102,7 @@
}
/** The locator instance for identifying the document, line, and column number of specific elements. */
- private Locator locator;
+ private Locator2 locator;
/** The logger. */
private Logger logger = LoggerFactory.getLogger(this.getClass());
@@ -139,7 +140,7 @@
@Override
public void setDocumentLocator(final Locator locator) {
- this.locator = locator;
+ this.locator = (Locator2) locator;
}
/**
@@ -240,7 +241,10 @@
/* Standard SAX features and properties. */
+ assertFeature(xmlReader, SaxStdFeatures.USE_ATTRIBUTES2, true, Level.ERROR);
+ assertFeature(xmlReader, SaxStdFeatures.USE_LOCATOR2, true, Level.ERROR);
+
setFeature(xmlReader, SaxStdFeatures.NAMESPACES, namespacePrefixes, Level.ERROR);
setFeature(xmlReader, SaxStdFeatures.NAMESPACE_PREFIXES, namespacePrefixes, Level.ERROR);
/* Turn on validation if it is available. */
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-02-03 13:39:58
|
Revision: 13110
http://sourceforge.net/p/foray/code/13110
Author: victormote
Date: 2023-02-03 13:39:56 +0000 (Fri, 03 Feb 2023)
Log Message:
-----------
Use attributes2 feature to skip any attributes that were implied as defaults and did not exist in the parsed text.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java 2023-02-03 13:38:22 UTC (rev 13109)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java 2023-02-03 13:39:56 UTC (rev 13110)
@@ -41,12 +41,14 @@
import org.apache.ws.commons.schema.XmlSchemaElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.slf4j.event.Level;
import org.xml.sax.Attributes;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
-import org.xml.sax.helpers.AttributesImpl;
+import org.xml.sax.ext.Attributes2;
+import org.xml.sax.ext.Attributes2Impl;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@@ -112,7 +114,7 @@
private String lastStartedElement;
/** The attributes belonging to the last-started element. */
- private Attributes lastStartedAttributes;
+ private Attributes2 lastStartedAttributes;
/** The last column number that was written. This value is one-based, i.e. after the first character is written on a
* new line, this value should be 1. */
@@ -182,6 +184,9 @@
public Object parse(final InputSource inputSource) throws IOException, SAXException {
final EntityResolver entityResolver = SaxUtils.getEntityResolver(catalogs);
final XMLReader parser = createSax2Parser(true, true, true, entityResolver, true);
+
+ assertFeature(parser, SaxStdFeatures.USE_ATTRIBUTES2, true, Level.ERROR);
+
parser.parse(inputSource);
cleanup();
return null;
@@ -223,7 +228,7 @@
* element, and empty elements can be written two different ways.*/
this.lastStartedElement = qName;
/* Must copy the attributes as they are reset on each callback. */
- this.lastStartedAttributes = new AttributesImpl(attributes);
+ this.lastStartedAttributes = new Attributes2Impl(attributes);
if (getDtd() == null) {
final QName qname = new QName(uri, local);
final XmlSchemaElement schemaElement = getSchemaElement(qname);
@@ -259,7 +264,7 @@
* @param attributes The attributes for the element to be written.
* @param isEmpty Indicates whether the element has any content or not.
*/
- private void writeElement(final String qName, final Attributes attributes, final boolean isEmpty) {
+ private void writeElement(final String qName, final Attributes2 attributes, final boolean isEmpty) {
if (qName == null) {
return;
}
@@ -277,11 +282,15 @@
/* Accumulate the attributes. */
final StringBuilder attributesBuffer = new StringBuilder();
for (int i = 0; i < attributes.getLength(); i++) {
- attributesBuffer.append(" ");
- attributesBuffer.append(attributes.getQName(i));
- attributesBuffer.append("=\"");
- attributesBuffer.append(attributes.getValue(i));
- attributesBuffer.append("\"");
+ /* Check "isSpecified" to eliminate any attributes that were included by the parser as a default, in other
+ * words, attributes that did not actually exist in the parsed text. */
+ if (attributes.isSpecified(i)) {
+ attributesBuffer.append(" ");
+ attributesBuffer.append(attributes.getQName(i));
+ attributesBuffer.append("=\"");
+ attributesBuffer.append(attributes.getValue(i));
+ attributesBuffer.append("\"");
+ }
}
/* Accumulate the tag closer. */
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-02-03 13:38:24
|
Revision: 13109
http://sourceforge.net/p/foray/code/13109
Author: victormote
Date: 2023-02-03 13:38:22 +0000 (Fri, 03 Feb 2023)
Log Message:
-----------
Add method that subclasses can use to assert that a given feature is available in the parser.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java 2023-02-03 13:01:45 UTC (rev 13108)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java 2023-02-03 13:38:22 UTC (rev 13109)
@@ -274,7 +274,7 @@
* @param feature The name of the feature.
* @param value The value of the feature.
* @param loggingLevel The logging level to which any exceptions should be logged. A logging level of null implies
- * that the exception rethrown instead of logged.
+ * that the exception should be rethrown instead of logged.
*/
private void setFeature(final XMLReader xmlReader, final String feature, final boolean value,
final org.slf4j.event.Level loggingLevel) throws SAXException {
@@ -296,6 +296,43 @@
}
/**
+ * Convenience method used to check parser features.
+ * @param xmlReader The reader on which the feature is being checked.
+ * @param feature The feature being tested.
+ * @param expectedValue The expected value of {@code feature}.
+ * @param loggingLevel The logging level to which any exceptions or assertion failures should be logged.
+ * @throws SAXException For unrecognized features, unsupported features, or assertion failures, when the logging
+ * level has not been set.
+ */
+ protected void assertFeature(final XMLReader xmlReader, final String feature, final boolean expectedValue,
+ final org.slf4j.event.Level loggingLevel) throws SAXException {
+ try {
+ final boolean value = xmlReader.getFeature(feature);
+ if (value != expectedValue) {
+ final String message = "Parser feature failure. Feature: " + feature + ", Expected: " + expectedValue
+ + ", Actual: " + value;
+ if (loggingLevel == null) {
+ throw new SAXException(message);
+ } else {
+ this.logger.atLevel(loggingLevel).log(message);
+ }
+ }
+ } catch (final SAXNotRecognizedException e) {
+ if (loggingLevel == null) {
+ throw e;
+ } else {
+ this.logger.atLevel(loggingLevel).log("SAX2 parser does not recognize feature: " + feature);
+ }
+ } catch (final SAXNotSupportedException e) {
+ if (loggingLevel == null) {
+ throw e;
+ } else {
+ this.logger.atLevel(loggingLevel).log("SAX2 parser does not support feature: " + feature);
+ }
+ }
+ }
+
+ /**
* Convenience method used to set parser properties, handling exceptions with appropriate log messages.
* @param xmlReader The reader to which the property should be set.
* @param property The name of the property.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-02-03 13:01:48
|
Revision: 13108
http://sourceforge.net/p/foray/code/13108
Author: victormote
Date: 2023-02-03 13:01:45 +0000 (Fri, 03 Feb 2023)
Log Message:
-----------
Fix error in setting of parser features.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java 2023-02-03 13:00:51 UTC (rev 13107)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java 2023-02-03 13:01:45 UTC (rev 13108)
@@ -279,7 +279,7 @@
private void setFeature(final XMLReader xmlReader, final String feature, final boolean value,
final org.slf4j.event.Level loggingLevel) throws SAXException {
try {
- xmlReader.setFeature(SaxStdFeatures.NAMESPACE_PREFIXES, value);
+ xmlReader.setFeature(feature, value);
} catch (final SAXNotRecognizedException e) {
if (loggingLevel == null) {
throw e;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-02-03 13:00:54
|
Revision: 13107
http://sourceforge.net/p/foray/code/13107
Author: victormote
Date: 2023-02-03 13:00:51 +0000 (Fri, 03 Feb 2023)
Log Message:
-----------
Pull remaining documentation into the javadoc, for developer convenience.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxStdFeatures.java
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxStdFeatures.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxStdFeatures.java 2023-02-03 01:06:43 UTC (rev 13106)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxStdFeatures.java 2023-02-03 13:00:51 UTC (rev 13107)
@@ -36,21 +36,26 @@
*/
public final class SaxStdFeatures {
- /** SAX feature "external-general-entities". */
+ /** SAX feature "external-general-entities". Reports whether this parser processes external general entities; always
+ * true if validating. Read/write, default unspecified. */
public static final String EXTERNAL_GENERAL_ENTITIES = "http://xml.org/sax/features/external-general-entities";
- /** SAX feature "external-parameter-entities". */
+ /** SAX feature "external-parameter-entities". Reports whether this parser processes external parameter entities;
+ * always true if validating. Read/write, default unspecified. */
public static final String EXTERNAL_PARAMETER_ENTITIES = "http://xml.org/sax/features/external-parameter-entities";
- /** SAX feature "is-standalone". */
+ /** SAX feature "is-standalone". May be examined only during a parse, after the startDocument() callback has been
+ * completed; read-only. The value is true if the document specified standalone="yes" in its XML declaration, and
+ * otherwise is false. Read-only. */
public static final String IS_STANDALONE = "http://xml.org/sax/features/is-standalone";
- /** SAX feature "lexical-handler/parameter-entities". */
+ /** SAX feature "lexical-handler/parameter-entities". A value of "true" indicates that the LexicalHandler will
+ * report the beginning and end of parameter entities. Read/write, default unspecified. */
public static final String LEXICAL_HANDLER_PARAMETER_ENTITIES =
"http://xml.org/sax/features/lexical-handler/parameter-entities";
/** SAX feature "namespaces". A value of "true" indicates namespace URIs and unprefixed local names for element and
- * attribute names will be available. */
+ * attribute names will be available. Read/write, default true. */
public static final String NAMESPACES = "http://xml.org/sax/features/namespaces";
/** SAX feature "namespace-prefixes". A value of "true" indicates that XML qualified names (with prefixes) and
@@ -57,23 +62,46 @@
* attributes (including xmlns* attributes) will be available. Read/write, default false. */
public static final String NAMESPACE_PREFIXES = "http://xml.org/sax/features/namespace-prefixes";
- /** SAX feature "resolve-dtd-uris". */
+ /** <p>SAX feature "resolve-dtd-uris". A value of "true" indicates that system IDs in declarations will be
+ * absolutized (relative to their base URIs) before reporting. (That is the default behavior for all SAX2 XML
+ * parsers.) A value of "false" indicates those IDs will not be absolutized; parsers will provide the base URI from
+ * Locator.getSystemId(). This applies to system IDs passed in</p>
+ * <ul>
+ * <li>DTDHandler.notationDecl(),</li>
+ * <li>DTDHandler.unparsedEntityDecl(), and</li>
+ * <li>DeclHandler.externalEntityDecl().</li>
+ * </ul>
+ * <p>It does not apply to EntityResolver.resolveEntity(), which is not used to report declarations, or to
+ * LexicalHandler.startDTD(), which already provides the non-absolutized URI. Read/write, default true. </p> */
public static final String RESOLVE_DTD_URIS = "http://xml.org/sax/features/resolve-dtd-uris";
- /** SAX feature "string-interning". */
+ /** SAX feature "string-interning". Has a value of "true" if all XML names (for elements, prefixes, attributes,
+ * entities, notations, and local names), as well as Namespace URIs, will have been interned using
+ * java.lang.String.intern. This supports fast testing of equality/inequality against string constants, rather than
+ * forcing slower calls to String.equals(). Read/write, default unspecified. */
public static final String STRING_INTERNING = "http://xml.org/sax/features/string-interning";
- /** SAX feature "unicode-normalization-checking". */
+ /** SAX feature "unicode-normalization-checking". Controls whether the parser reports Unicode normalization errors
+ * as described in section 2.13 and Appendix B of the XML 1.1 Recommendation. If true, Unicode normalization errors
+ * are reported using the ErrorHandler.error() callback. Such errors are not fatal in themselves (though, obviously,
+ * other Unicode-related encoding errors may be). Read/write, default false. */
public static final String UNICODE_NORMALIZATION_CHECKING =
"http://xml.org/sax/features/unicode-normalization-checking";
- /** SAX feature "use-attributes2". */
+ /** SAX feature "use-attributes2". Returns "true" if the Attributes objects passed by this parser in
+ * ContentHandler.startElement() implement the org.xml.sax.ext.Attributes2 interface. That interface exposes
+ * additional DTD-related information, such as whether the attribute was specified in the source text rather than
+ * defaulted. Read-only. */
public static final String USE_ATTRIBUTES2 = "http://xml.org/sax/features/use-attributes2";
- /** SAX feature "use-locator2". */
+ /** SAX feature "use-locator2". Returns "true" if the Locator objects passed by this parser in
+ * ContentHandler.setDocumentLocator() implement the org.xml.sax.ext.Locator2 interface. That interface exposes
+ * additional entity information, such as the character encoding and XML version used. Read-only. */
public static final String USE_LOCATOR2 = "http://xml.org/sax/features/use-locator2";
- /** SAX feature "use-entity-resolver2". */
+ /** SAX feature "use-entity-resolver2". Returns "true" if, when setEntityResolver is given an object implementing
+ * the org.xml.sax.ext.EntityResolver2 interface, those new methods will be used. Returns "false" to indicate that
+ * those methods will not be used. Read/write, default true. */
public static final String USE_ENTITY_RESOLVER2 = "http://xml.org/sax/features/use-entity-resolver2";
/** SAX feature "validation". Controls whether the parser is reporting all validity errors; if true, all external
@@ -80,7 +108,12 @@
* entities will be read. Read/write, default unspecified. */
public static final String VALIDATION = "http://xml.org/sax/features/validation";
- /** SAX feature "xmlns-uris". */
+ /** SAX feature "xmlns-uris". Controls whether, when the namespace-prefixes feature is set, the parser treats
+ * namespace declaration attributes as being in the http://www.w3.org/2000/xmlns/ namespace. By default, SAX2
+ * conforms to the original "Namespaces in XML" Recommendation, which explicitly states that such attributes are not
+ * in any namespace. Setting this optional flag to "true" makes the SAX2 events conform to a later
+ * backwards-incompatible revision of that recommendation, placing those attributes in a namespace. Read/write,
+ * default false. */
public static final String XMLNS_URIS = "http://xml.org/sax/features/xmlns-uris";
/** SAX feature "xml-1.1". Returns "true" if the parser supports both XML 1.1 and XML 1.0. Returns "false" if the
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-02-03 01:06:47
|
Revision: 13106
http://sourceforge.net/p/foray/code/13106
Author: victormote
Date: 2023-02-03 01:06:43 +0000 (Fri, 03 Feb 2023)
Log Message:
-----------
Minor doc and whitespace changes only.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java
trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxStdFeatures.java
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java 2023-01-31 21:59:33 UTC (rev 13105)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java 2023-02-03 01:06:43 UTC (rev 13106)
@@ -63,8 +63,7 @@
import javax.xml.namespace.QName;
/**
- * Command-line application that reads an XML file and writes a pretty-printed
- * version of it.
+ * Reads an XML file and writes a pretty-printed version of it.
*/
public class ForayPretty extends SaxParser<Object> {
@@ -77,8 +76,7 @@
/** Command-line return status constant indicating that there was an error parsing the input file. */
public static final byte STATUS_PARSING_ERROR = 3;
- /** The default line length that should be used in the pretty-printed
- * output. */
+ /** The default line length that should be used in the pretty-printed output. */
private static final byte DEFAULT_LINE_LENGTH = 80;
/** The output stream to which the pretty-printed output should be sent. */
@@ -116,9 +114,8 @@
/** The attributes belonging to the last-started element. */
private Attributes lastStartedAttributes;
- /** The last column number that was written. This value is one-based, i.e.
- * After the first character is written on a new line, this value should be
- * 1. */
+ /** The last column number that was written. This value is one-based, i.e. after the first character is written on a
+ * new line, this value should be 1. */
private int lastColumnWritten = 0;
/* End state variables. */
@@ -140,8 +137,7 @@
/** The text that should be output after the root element. */
private String postRootText = "\n";
- /** Set this to true if PCDATA content can have space characters replaced
- * by line terminators and vice versa. */
+ /** Set this to true if PCDATA content can have space characters replaced by line terminators and vice versa. */
private boolean breakPCDATA = true;
/** The number of spaces that should be indented for each level. */
@@ -151,10 +147,10 @@
private int desiredLineLength = ForayPretty.DEFAULT_LINE_LENGTH;
/**
- * Block elements are started on a new line. However, if they are inside
- * elements containing mixed content, the default behavior is to start the
- * element at column 0. If it should be indented, set this variable to
- * true.
+ * Block elements are started on a new line.
+ * However, if they are inside elements containing mixed content, the default behavior is to start the element at
+ * column 0.
+ * If it should be indented, set this variable to true.
*/
private boolean indentBlocksInsideMixedContent = false;
@@ -223,9 +219,8 @@
/* Cache the parameters in instance variable for later processing.
- * We don't want to write the element yet, because the next event
- * received might be the close of the same element, and empty elements
- * can be written two different ways.*/
+ * We don't want to write the element yet, because the next event received might be the close of the same
+ * element, and empty elements can be written two different ways.*/
this.lastStartedElement = qName;
/* Must copy the attributes as they are reset on each callback. */
this.lastStartedAttributes = new AttributesImpl(attributes);
@@ -247,8 +242,7 @@
}
/**
- * Writes the element at the top of the stack if it has not already been
- * written.
+ * Writes the element at the top of the stack if it has not already been written.
* @param isEmpty Indicates whether the element has any content or not.
*/
private void ensureTopElementWritten(final boolean isEmpty) {
@@ -255,8 +249,7 @@
if (this.topElementWritten) {
return;
}
- writeElement(this.lastStartedElement, this.lastStartedAttributes,
- isEmpty);
+ writeElement(this.lastStartedElement, this.lastStartedAttributes, isEmpty);
this.topElementWritten = true;
}
@@ -266,8 +259,7 @@
* @param attributes The attributes for the element to be written.
* @param isEmpty Indicates whether the element has any content or not.
*/
- private void writeElement(final String qName, final Attributes attributes,
- final boolean isEmpty) {
+ private void writeElement(final String qName, final Attributes attributes, final boolean isEmpty) {
if (qName == null) {
return;
}
@@ -314,8 +306,7 @@
}
/* Queue up the attributes and tag close. */
- this.queue.add(attributesBuffer.toString()
- + tagCloseBuffer.toString());
+ this.queue.add(attributesBuffer.toString() + tagCloseBuffer.toString());
}
/**
@@ -356,8 +347,7 @@
}
@Override
- public void endElement(final String uri, final String local,
- final String qName) {
+ public void endElement(final String uri, final String local, final String qName) {
flushCharacters();
if (this.topElementWritten) {
@@ -383,11 +373,9 @@
}
/**
- * Determines whether the start tag for the current element should
- * be written on a new line or whether it should be written inside the
- * parent tag.
- * @return True if the start tag for the current element should be written
- * on a new line.
+ * Determines whether the start tag for the current element should be written on a new line or whether it should be
+ * written inside the parent tag.
+ * @return True if the start tag for the current element should be written on a new line.
*/
private boolean startTagOnNewLine() {
return this.elementStack.topIsBlockElement();
@@ -394,18 +382,15 @@
}
/**
- * Determines whether the end tag for the current element should
- * be written on a new line or whether it should be written immediately
- * after the contents.
- * @return True if the end tag for the current element should be written on
- * a new line.
+ * Determines whether the end tag for the current element should be written on a new line or whether it should be
+ * written immediately after the contents.
+ * @return True if the end tag for the current element should be written on a new line.
*/
private boolean endTagOnNewLine() {
if (! this.elementStack.topIsBlockElement()) {
return false;
}
- /* If the current element contains PCDATA, the end tag should be
- * written in-line instead of on a new line. */
+ /* If the current element contains PCDATA, the end tag should be written in-line instead of on a new line. */
if (this.elementStack.topHasPCDATA()) {
return false;
}
@@ -416,8 +401,8 @@
public void characters(final char[] buffer, final int offset,
final int length) {
if (this.inEntity) {
- /* Skip these characters. We are writing the unexpanded entity
- * elsewhere. We do not want to also write the expanded version. */
+ /* Skip these characters. We are writing the unexpanded entity elsewhere. We do not want to also write the
+ * expanded version. */
return;
}
this.charBuffer.append(buffer, offset, length);
@@ -461,14 +446,12 @@
}
@Override
- public void ignorableWhitespace(final char[] buffer, final int offset,
- final int length) {
+ public void ignorableWhitespace(final char[] buffer, final int offset, final int length) {
/* Ignorable white space is just ignored. */
}
@Override
- public void comment(final char[] buffer, final int offset,
- final int length) {
+ public void comment(final char[] buffer, final int offset, final int length) {
if (this.inDTD) {
return;
}
@@ -500,8 +483,7 @@
}
@Override
- public void startDTD(final String name, final String publicId,
- final String systemId) {
+ public void startDTD(final String name, final String publicId, final String systemId) {
write(newLine());
write("<!DOCTYPE ");
write(name);
@@ -549,17 +531,15 @@
}
/**
- * Use this method if the content may contain \n characters that need to be
- * converted to the output line-ending.
+ * Use this method if the content may contain \n characters that need to be converted to the output line-ending.
* SAX converts all line-endings, regardless of platform, to \n.
- * Do not use this method for output that has specified line-endings in it,
- * as that may result in the conversion of \r\n to \r\r\n, for example.
+ * Do not use this method for output that has specified line-endings in it, as that may result in the conversion of
+ * \r\n to \r\r\n, for example.
* @param outputString The String that should be written.
*/
private void writeRawPCDATA(final String outputString) {
if (this.lineTerminator.equals("\n")) {
- /* The specified line terminator is the same as that used in the
- * input. Just write it. */
+ /* The specified line terminator is the same as that used in the input. Just write it. */
write(outputString);
return;
}
@@ -573,8 +553,7 @@
int bufferIndex = 0;
while (bufferIndex < buffer.length()) {
if (buffer.charAt(bufferIndex) == '\n') {
- buffer.replace(bufferIndex, bufferIndex + 1,
- this.lineTerminator);
+ buffer.replace(bufferIndex, bufferIndex + 1, this.lineTerminator);
bufferIndex += this.lineTerminator.length();
} else {
bufferIndex ++;
@@ -601,8 +580,7 @@
} catch (final IOException e) {
errorMessage("Error converting text.");
}
- final int lastLineBreakIndex = outputString.lastIndexOf(
- this.lineTerminator);
+ final int lastLineBreakIndex = outputString.lastIndexOf(this.lineTerminator);
if (lastLineBreakIndex < 0) {
/* No line breaks in what is being written. Increment the current
* column by the length of outputString. Note that we want the
@@ -609,15 +587,14 @@
* count of characters, not bytes, here. */
this.lastColumnWritten += outputString.length();
} else {
- this.lastColumnWritten = outputString.length() - lastLineBreakIndex
- - this.lineTerminator.length();
+ this.lastColumnWritten = outputString.length() - lastLineBreakIndex - this.lineTerminator.length();
}
}
/**
* Compute the current indentation level.
- * @return The number of indents for the current state. This is the number
- * of levels that should be indented, not necessarily the number of spaces.
+ * @return The number of indents for the current state. This is the number of levels that should be indented, not
+ * necessarily the number of spaces.
*/
private int currentIndentation() {
return this.elementStack.size() - 1;
@@ -628,27 +605,25 @@
*/
private class Queue {
- /** Collection of Strings that need to be written as soon as we know
- * enough of what comes after them to choose line breaks. This is needed
- * for PCDATA and inline tags that must stay on the current line.
- * It is tempting to turn this all into one long {@link StringBuilder}, but we
- * need to handle attributes differently from PCDATA. */
+ /** Collection of Strings that need to be written as soon as we know enough of what comes after them to choose
+ * line breaks.
+ * This is needed for PCDATA and inline tags that must stay on the current line.
+ * It is tempting to turn this all into one long {@link StringBuilder}, but we need to handle attributes
+ * differently from PCDATA. */
private List<String> toWriteQueue = new ArrayList<String>();
- /** After running listBreakOpportunities, this array, along with
- * {@link #breakOpportunityIndexes}, holds a list of
- * break opportunities. This array contains a list of items in
- * toWriteQueue. */
+ /** After running listBreakOpportunities, this array, along with {@link #breakOpportunityIndexes}, holds a list
+ * of break opportunities.
+ * This array contains a list of items in toWriteQueue. */
private int[] breakOpportunityItems;
- /** After running listBreakOpportunities, this array, along with
- * {@link #breakOpportunityItems}, holds a list of
- * break opportunities. This array points to a specific character
- * in the "items" array. */
+ /** After running listBreakOpportunities, this array, along with {@link #breakOpportunityItems}, holds a list of
+ * break opportunities.
+ * This array points to a specific character in the "items" array. */
private int[] breakOpportunityIndexes;
- /** List of Integer indexes into the breakOpportunity arrays that
- * indicate which opportunities have actually been chosen. */
+ /** List of Integer indexes into the breakOpportunity arrays that indicate which opportunities have actually
+ * been chosen. */
private List<Integer> breaksChosen = new ArrayList<Integer>();
/**
@@ -683,8 +658,7 @@
/* Loop one extra time to catch the last chunk. */
for (int i = 0; i <= this.breakOpportunityIndexes.length; i++) {
int sizeIfAccepted = 0;
- /* If it is the first item, we must consider what has already
- * been written on the line. */
+ /* If it is the first item, we must consider what has already been written on the line. */
if (this.breaksChosen.size() < 1) {
sizeIfAccepted += ForayPretty.this.lastColumnWritten;
}
@@ -693,9 +667,8 @@
if (sizeIfAccepted > ForayPretty.this.desiredLineLength) {
int breakSelected = i - 1;
if (breakSelected <= this.getLastBreakChosen()) {
- /* Don't let the same break get chosen again. If the
- * content is too long, we still need to write it
- * once. */
+ /* Don't let the same break get chosen again. If the content is too long, we still need to write
+ * it once. */
breakSelected = this.getLastBreakChosen() + 1;
}
this.breaksChosen.add(breakSelected);
@@ -704,14 +677,13 @@
}
/**
- * If everything can be written on the current line, do it. Otherwise,
- * do nothing.
+ * If everything can be written on the current line, do it.
+ * Otherwise, do nothing.
* @return True if everything was written, false otherwise.
*/
private boolean attemptWriteAll() {
/* If they all fit on the current line, write them all. */
- if (charCount() + ForayPretty.this.lastColumnWritten
- <= ForayPretty.this.desiredLineLength) {
+ if (charCount() + ForayPretty.this.lastColumnWritten <= ForayPretty.this.desiredLineLength) {
writeAll();
return true;
}
@@ -1003,10 +975,10 @@
}
/**
- * Set this configuration parameter to true if whitespace within PCDATA can
- * be interchanged. Specifically, if this parameter is set, tabs will be
- * normalized to spaces, duplicate spaces will be removed, and spaces and
- * new-lines will be treated as interchangeable. The default value is true.
+ * Set this configuration parameter to true if whitespace within PCDATA can be interchanged.
+ * Specifically, if this parameter is set, tabs will be normalized to spaces, duplicate spaces will be removed, and
+ * spaces and new-lines will be treated as interchangeable.
+ * The default value is true.
* @param breakPCDATA The new value.
*/
public void setBreakPCDATA(final boolean breakPCDATA) {
@@ -1014,9 +986,9 @@
}
/**
- * Use this configuration parameter to set the value of the XML Declaration
- * at the beginning of the pretty-printed document. The default value is
- * {@code <?xml version="1.0" encoding="UTF-8">}
+ * Use this configuration parameter to set the value of the XML Declaration at the beginning of the pretty-printed
+ * document.
+ * The default value is {@code <?xml version="1.0" encoding="UTF-8">}.
* @param xmlDeclaration The new value.
*/
public void setXmlDeclaration(final String xmlDeclaration) {
@@ -1024,10 +996,11 @@
}
/**
- * Use this configuration parameter to set the text that should be used
- * to delimit lines in the pretty-printed document. The default is
- * platform-specific. On Unix, for example, it is "\n". On Windows, it is
- * "\r\n".
+ * Use this configuration parameter to set the text that should be used to delimit lines in the pretty-printed
+ * document.
+ * The default is platform-specific.
+ * On Unix, for example, it is "\n".
+ * On Windows, it is "\r\n".
* @param lineTerminator The new value.
*/
public void setLineTerminator(final String lineTerminator) {
@@ -1035,8 +1008,8 @@
}
/**
- * Use this configuration parameter to set the output encoding for the
- * pretty-printed document. The default value is "UTF-8".
+ * Use this configuration parameter to set the output encoding for the pretty-printed document.
+ * The default value is "UTF-8".
* @param outputEncoding The new value.
*/
public void setOutputEncoding(final String outputEncoding) {
@@ -1044,10 +1017,9 @@
}
/**
- * Use this configuration parameter to control the text that is written
- * right before the root element.
- * Any text between the Dtd and the root element in the source document is
- * considered to be insignificant and is therefore stripped out.
+ * Use this configuration parameter to control the text that is written right before the root element.
+ * Any text between the Dtd and the root element in the source document is considered to be insignificant and is
+ * therefore stripped out.
* The default value is null.
* @param preRootText The new value.
*/
@@ -1056,10 +1028,9 @@
}
/**
- * Use this configuration parameter to control the text that is written
- * right after the close of the root element.
- * Any text after the root element in the source document is considered to
- * be insignificant and is therefore stripped out.
+ * Use this configuration parameter to control the text that is written right after the close of the root element.
+ * Any text after the root element in the source document is considered to be insignificant and is therefore
+ * stripped out.
* The default value is "\n" (one line-feed).
* @param postRootText The new value.
*/
@@ -1068,9 +1039,9 @@
}
/**
- * Use this configuration parameter to set the number of spaces that each
- * successive block level of the document should be indented. The default
- * is 2.
+ * Use this configuration parameter to set the number of spaces that each successive block level of the document
+ * should be indented.
+ * The default is 2.
* @param indent The new value.
*/
public void setIndent(final int indent) {
@@ -1078,8 +1049,9 @@
}
/**
- * Use this configuration parameter to set the desired maximum line length,
- * in characters, for the pretty-printed document. The default is 80.
+ * Use this configuration parameter to set the desired maximum line length, in characters, for the pretty-printed
+ * document.
+ * The default is 80.
* @param desiredLineLength The new value.
*/
public void setDesiredLineLength(final int desiredLineLength) {
@@ -1087,8 +1059,8 @@
}
/**
- * Set this configuration parameter to true if blocks that are inside of
- * mixed content should be indented. The default is "false".
+ * Set this configuration parameter to true if blocks that are inside of mixed content should be indented.
+ * The default is "false".
* @param indent The new value.
*/
public void setIndentBlocksInsideMixedContent(final boolean indent) {
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxStdFeatures.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxStdFeatures.java 2023-01-31 21:59:33 UTC (rev 13105)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxStdFeatures.java 2023-02-03 01:06:43 UTC (rev 13106)
@@ -36,8 +36,6 @@
*/
public final class SaxStdFeatures {
- /* TODO: Only currently-used features are included in this enumeration. Add remaining features as needed. */
-
/** SAX feature "external-general-entities". */
public static final String EXTERNAL_GENERAL_ENTITIES = "http://xml.org/sax/features/external-general-entities";
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-01-31 21:59:36
|
Revision: 13105
http://sourceforge.net/p/foray/code/13105
Author: victormote
Date: 2023-01-31 21:59:33 +0000 (Tue, 31 Jan 2023)
Log Message:
-----------
Improvements to pretty-printing XML using shema for its model.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java
trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XsdElement.java
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java 2023-01-31 21:09:41 UTC (rev 13104)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java 2023-01-31 21:59:33 UTC (rev 13105)
@@ -977,7 +977,7 @@
}
}
if (startIndex > -1
- && endIndex > startIndex) {
+ && endIndex > -1) {
final String stringToWrite = string.substring(startIndex, endIndex + 1);
write(stringToWrite);
}
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XsdElement.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XsdElement.java 2023-01-31 21:09:41 UTC (rev 13104)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XsdElement.java 2023-01-31 21:59:33 UTC (rev 13105)
@@ -57,8 +57,7 @@
@Override
public boolean hasPCDATA() {
- // TODO Auto-generated method stub
- return false;
+ return element.getSchemaType().isMixed();
}
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-01-31 21:09:44
|
Revision: 13104
http://sourceforge.net/p/foray/code/13104
Author: victormote
Date: 2023-01-31 21:09:41 +0000 (Tue, 31 Jan 2023)
Log Message:
-----------
Improvements to XSD parsing.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java
trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java
trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/DtdElement.java
Added Paths:
-----------
trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XsdElement.java
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java 2023-01-31 17:59:21 UTC (rev 13103)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/ForayPretty.java 2023-01-31 21:09:41 UTC (rev 13104)
@@ -28,8 +28,8 @@
package org.foray.xml;
-import org.foray.xml.dtd.DtdElement;
import org.foray.xml.dtd.ElementStack;
+import org.foray.xml.model.XsdElement;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
@@ -38,6 +38,7 @@
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
+import org.apache.ws.commons.schema.XmlSchemaElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
@@ -57,7 +58,10 @@
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
+import javax.xml.namespace.QName;
+
/**
* Command-line application that reads an XML file and writes a pretty-printed
* version of it.
@@ -94,19 +98,16 @@
/* Begin state variables. */
- /** State variable tracking whether we are currently inside the Dtd or
- * not. */
+ /** State variable tracking whether we are currently inside the Dtd or not. */
private boolean inDTD = false;
- /** State variable tracking whether we are currently inside an entity
- * expansion or not. */
+ /** State variable tracking whether we are currently inside an entity expansion or not. */
private boolean inEntity = false;
/** State variable tracking whether we are currently inside a CDATA section or not. */
private boolean inCdata = false;
- /** Indicates whether the item on the top of the element stack has been
- * written. */
+ /** Indicates whether the item on the top of the element stack has been written. */
private boolean topElementWritten = true;
/** The name of the last started-element. */
@@ -128,8 +129,7 @@
private String outputEncoding = "UTF-8";
/** The XML declaration string. */
- private String xmlDeclaration = "<?xml version=\"1.0\" "
- + "encoding=\"" + this.outputEncoding + "\"?>";
+ private String xmlDeclaration = "<?xml version=\"1.0\" encoding=\"" + this.outputEncoding + "\"?>";
/** The line terminator that should be used in the output. */
private String lineTerminator = "\n";
@@ -229,8 +229,20 @@
this.lastStartedElement = qName;
/* Must copy the attributes as they are reset on each callback. */
this.lastStartedAttributes = new AttributesImpl(attributes);
- final DtdElement element = getDtd().getElement(qName);
- this.elementStack.push(element);
+ if (getDtd() == null) {
+ final QName qname = new QName(uri, local);
+ final XmlSchemaElement schemaElement = getSchemaElement(qname);
+
+ final Map<XmlSchemaElement, XsdElement> schemaElementMap = getSchemaElementMap();
+ XsdElement xsdElement = schemaElementMap.get(schemaElement);
+ if (xsdElement == null) {
+ xsdElement = new XsdElement(schemaElement);
+ schemaElementMap.put(schemaElement, xsdElement);
+ }
+ this.elementStack.push(xsdElement);
+ } else {
+ this.elementStack.push(getDtd().getElement(qName));
+ }
this.topElementWritten = false;
}
@@ -964,8 +976,8 @@
endIndex --;
}
}
- if (startIndex >= 0
- && endIndex >= 0) {
+ if (startIndex > -1
+ && endIndex > startIndex) {
final String stringToWrite = string.substring(startIndex, endIndex + 1);
write(stringToWrite);
}
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java 2023-01-31 17:59:21 UTC (rev 13103)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java 2023-01-31 21:09:41 UTC (rev 13104)
@@ -31,8 +31,10 @@
import org.foray.primitive.StringUtils;
import org.foray.xml.dtd.Dtd;
import org.foray.xml.dtd.DtdElement;
+import org.foray.xml.model.XsdElement;
import org.apache.ws.commons.schema.XmlSchemaCollection;
+import org.apache.ws.commons.schema.XmlSchemaElement;
import org.apache.ws.commons.schema.resolver.URIResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -54,9 +56,12 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
import java.util.StringTokenizer;
import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
import javax.xml.transform.stream.StreamSource;
/**
@@ -81,11 +86,14 @@
private static final int MAX_EXPECTED_TEXT_LENGTH = 4096;
/** The Dtd for this document, which can be null. */
- private Dtd dtd = new Dtd();
+ private Dtd dtd;
/** The XML Schema for this document, which can be null. */
private XmlSchemaCollection schemaCollection;
+ /** Map whose key is an (Apache) schema element, and whose value is a (FOray) schema element. */
+ private Map<XmlSchemaElement, XsdElement> schemaElementMap = new HashMap<XmlSchemaElement, XsdElement>();
+
/* Register the URLStreamHandler for classpath: URLs.
* This has to be done only once, hence a static statement. */
static {
@@ -417,6 +425,9 @@
@Override
public void elementDecl(final String name, final String model) {
final DtdElement dtdElement = new DtdElement(name, model);
+ if (this.dtd == null) {
+ this.dtd = new Dtd();
+ }
this.dtd.addElement(dtdElement);
}
@@ -429,6 +440,14 @@
}
/**
+ * Returns the map of schema elements.
+ * @return The map of schema elements.
+ */
+ public Map<XmlSchemaElement, XsdElement> getSchemaElementMap() {
+ return this.schemaElementMap;
+ }
+
+ /**
* Checks a set of attributes to see whether they contain a reference to a schema that needs to be parsed.
* @param attributes The attributes being tested.
* @throws SAXException For problems opening, reading, or closing the schema file.
@@ -605,4 +624,13 @@
return attributeValue == null ? defaultValue : attributeValue;
}
+ /**
+ * Returns the (Apache) schema element for a given QName.
+ * @param qname The qname of the element to be returned.
+ * @return The (Apache) schema element matching {@code qname}.
+ */
+ public XmlSchemaElement getSchemaElement(final QName qname) {
+ return this.schemaCollection.getElementByQName(qname);
+ }
+
}
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/DtdElement.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/DtdElement.java 2023-01-31 17:59:21 UTC (rev 13103)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/DtdElement.java 2023-01-31 21:09:41 UTC (rev 13104)
@@ -31,7 +31,7 @@
import org.foray.xml.model.XmlModelElement;
/**
- * Represents an element declaration in an SGML/XML Document Type Definition (Dtd).
+ * An element declaration in an SGML/XML Document Type Definition (DTD).
*/
public class DtdElement implements XmlModelElement {
Added: trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XsdElement.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XsdElement.java (rev 0)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XsdElement.java 2023-01-31 21:09:41 UTC (rev 13104)
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2023 The FOray Project.
+ * http://www.foray.org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This work is in part derived from the following work(s), used with the
+ * permission of the licensor:
+ * Apache FOP, licensed by the Apache Software Foundation
+ *
+ */
+
+/*
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ * $LastChangedBy$
+ */
+
+package org.foray.xml.model;
+
+import org.apache.ws.commons.schema.XmlSchemaElement;
+
+/**
+ * An element declaration in an XML Schema (XSD).
+ * Wraps an instance of {@link XmlSchemaElement} .
+ */
+public class XsdElement implements XmlModelElement {
+
+ /** The wrapped element. */
+ private XmlSchemaElement element;
+
+ /**
+ * Constructor.
+ * @param element The wrapped element.
+ */
+ public XsdElement(final XmlSchemaElement element) {
+ this.element = element;
+ }
+
+ /**
+ * Returns the wrapped (Apache) schema element.
+ * @return The wrapped (Apache) schema element.
+ */
+ public XmlSchemaElement getXmlSchemaElement() {
+ return this.element;
+ }
+
+ @Override
+ public boolean hasPCDATA() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+}
Property changes on: trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XsdElement.java
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Rev
\ No newline at end of property
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-01-31 17:59:24
|
Revision: 13103
http://sourceforge.net/p/foray/code/13103
Author: victormote
Date: 2023-01-31 17:59:21 +0000 (Tue, 31 Jan 2023)
Log Message:
-----------
Create org.foray.xml.model package to handle model definitions that are agnostic of whether they were defined by DTD or XML Schema.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/DtdElement.java
trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/ElementStack.java
Added Paths:
-----------
trunk/foray/foray-xml/src/main/java/org/foray/xml/model/
trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XmlModelElement.java
trunk/foray/foray-xml/src/main/java/org/foray/xml/model/package-info.java
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/DtdElement.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/DtdElement.java 2023-01-31 17:32:10 UTC (rev 13102)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/DtdElement.java 2023-01-31 17:59:21 UTC (rev 13103)
@@ -28,11 +28,12 @@
package org.foray.xml.dtd;
+import org.foray.xml.model.XmlModelElement;
+
/**
- * Represents an element declaration in an SGML/XML Document Type Definition
- * (Dtd).
+ * Represents an element declaration in an SGML/XML Document Type Definition (Dtd).
*/
-public class DtdElement {
+public class DtdElement implements XmlModelElement {
/** The name of this element. */
private String elementName;
@@ -82,10 +83,7 @@
return this.elementName;
}
- /**
- * Indicates whether this element's content model contains PCDATA.
- * @return True if and only if this element's content model contains PCDATA.
- */
+ @Override
public boolean hasPCDATA() {
return this.hasPCDATA;
}
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/ElementStack.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/ElementStack.java 2023-01-31 17:32:10 UTC (rev 13102)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/dtd/ElementStack.java 2023-01-31 17:59:21 UTC (rev 13103)
@@ -28,16 +28,18 @@
package org.foray.xml.dtd;
+import org.foray.xml.model.XmlModelElement;
+
import java.util.ArrayList;
import java.util.List;
/**
- * A stack of DtdElement instances, useful when using a SAX parser.
+ * A stack of {@link XmlModelElement} instances.
*/
public class ElementStack {
/** The actual element stack. */
- private List<DtdElement> stack = new ArrayList<DtdElement>();
+ private List<XmlModelElement> stack = new ArrayList<XmlModelElement>();
/**
* Constructor.
@@ -49,10 +51,9 @@
* Push an item onto the stack.
* @param element The element to push onto the stack.
*/
- public void push(final DtdElement element) {
+ public void push(final XmlModelElement element) {
if (element == null) {
- throw new IllegalArgumentException("Cannot add a null item to the "
- + "element stack.");
+ throw new IllegalArgumentException("Cannot add a null item to the element stack.");
}
this.stack.add(element);
}
@@ -61,8 +62,8 @@
* Pop an item off of the stack.
* @return The popped element, or null if the stack is empty.
*/
- public DtdElement pop() {
- final DtdElement topElement = peek();
+ public XmlModelElement pop() {
+ final XmlModelElement topElement = peek();
if (topElement != null) {
this.stack.remove(this.stack.size() - 1);
}
@@ -73,19 +74,17 @@
* Peek at the top element on the stack without removing it from the stack.
* @return The top element on the stack.
*/
- public DtdElement peek() {
+ public XmlModelElement peek() {
return peek(0);
}
/**
- * Return an element from the stack without removing either it or anything
- * else from the stack.
- * @param indexFromTop The number of items deep in the stack the desired
- * element is. To get the top element, set to 0. To get the next element
- * down, set to 1, etc.
+ * Return an element from the stack without removing either it or anything else from the stack.
+ * @param indexFromTop The number of items deep in the stack the desired element is.
+ * To get the top element, set to 0. To get the next element down, set to 1, etc.
* @return The nth item down the stack, where n is indexFromTop.
*/
- private DtdElement peek(final int indexFromTop) {
+ private XmlModelElement peek(final int indexFromTop) {
if (this.stack.size() <= indexFromTop) {
return null;
}
@@ -110,17 +109,14 @@
}
/**
- * Reports whether the top element on the stack should be treated as a block
- * element or as an inline element.
- * A block element is any element whose immediate parent in the document
- * does not contain PCDATA.
- * Note that an element may be a block element but still be part of mixed
- * content, if some other ancestor does contain PCDATA.
- * @return True if and only if the top element on the stack is a block element, or if
- * the stack is empty.
+ * Reports whether the top element on the stack should be treated as a block element or as an inline element.
+ * A block element is any element whose immediate parent in the document does not contain PCDATA.
+ * Note that an element may be a block element but still be part of mixed content, if some other ancestor does
+ * contain PCDATA.
+ * @return True if and only if the top element on the stack is a block element, or if the stack is empty.
*/
public boolean topIsBlockElement() {
- final DtdElement parentElement = peek(1);
+ final XmlModelElement parentElement = peek(1);
if (parentElement == null) {
return true;
}
@@ -131,16 +127,14 @@
}
/**
- * Reports whether the top element on the stack is inside of any element
- * that contains mixed content.
- * @return True if and only if any ancestor element of the top of the stack can
- * contain PCDATA.
+ * Reports whether the top element on the stack is inside of any element that contains mixed content.
+ * @return True if and only if any ancestor element of the top of the stack can contain PCDATA.
*/
public boolean topIsInsideMixedContent() {
/* Start the loop at 1, because we don't care whether the top of the
* stack contains PCDATA or not. */
for (int i = 1; i < this.stack.size(); i++) {
- final DtdElement element = peek(i);
+ final XmlModelElement element = peek(i);
if (element == null) {
return false;
}
@@ -156,7 +150,7 @@
* @return True if and only if the top item on the stack contains PCDATA content.
*/
public boolean topHasPCDATA() {
- final DtdElement topElement = peek();
+ final XmlModelElement topElement = peek();
if (topElement == null) {
return false;
}
Added: trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XmlModelElement.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XmlModelElement.java (rev 0)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XmlModelElement.java 2023-01-31 17:59:21 UTC (rev 13103)
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2023 The FOray Project.
+ * http://www.foray.org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This work is in part derived from the following work(s), used with the
+ * permission of the licensor:
+ * Apache FOP, licensed by the Apache Software Foundation
+ *
+ */
+
+/*
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ * $LastChangedBy$
+ */
+
+package org.foray.xml.model;
+
+/**
+ * A generic XML Element type, agnostic of which model (DTD or XSD) was used to define it.
+ */
+public interface XmlModelElement {
+
+ /**
+ * Indicates whether this element's content model contains PCDATA.
+ * @return True if and only if this element's content model contains PCDATA.
+ */
+ boolean hasPCDATA();
+
+}
Property changes on: trunk/foray/foray-xml/src/main/java/org/foray/xml/model/XmlModelElement.java
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Rev
\ No newline at end of property
Added: trunk/foray/foray-xml/src/main/java/org/foray/xml/model/package-info.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/model/package-info.java (rev 0)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/model/package-info.java 2023-01-31 17:59:21 UTC (rev 13103)
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2023 The FOray Project.
+ * http://www.foray.org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This work is in part derived from the following work(s), used with the
+ * permission of the licensor:
+ * Apache FOP, licensed by the Apache Software Foundation
+ *
+ */
+
+/*
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ * $LastChangedBy$
+ */
+
+/**
+ * Interfaces shared by both DTD (document type definition) and XSD (XML schema definition) types.
+ */
+package org.foray.xml.model;
Property changes on: trunk/foray/foray-xml/src/main/java/org/foray/xml/model/package-info.java
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Rev
\ No newline at end of property
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-01-31 17:32:13
|
Revision: 13102
http://sourceforge.net/p/foray/code/13102
Author: victormote
Date: 2023-01-31 17:32:10 +0000 (Tue, 31 Jan 2023)
Log Message:
-----------
Improvements to XSD parsing.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java
Added Paths:
-----------
trunk/foray/foray-xml/src/main/java/org/foray/xml/EntityResolverUriResolver.java
Added: trunk/foray/foray-xml/src/main/java/org/foray/xml/EntityResolverUriResolver.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/EntityResolverUriResolver.java (rev 0)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/EntityResolverUriResolver.java 2023-01-31 17:32:10 UTC (rev 13102)
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2023 The FOray Project.
+ * http://www.foray.org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This work is in part derived from the following work(s), used with the
+ * permission of the licensor:
+ * Apache FOP, licensed by the Apache Software Foundation
+ *
+ */
+
+/*
+ * $LastChangedRevision$
+ * $LastChangedDate$
+ * $LastChangedBy$
+ */
+
+package org.foray.xml;
+
+import org.apache.ws.commons.schema.resolver.URIResolver;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+
+/**
+ * Implementation of {@link URIResolver} that wraps an {@link org.xml.sax.EntityResolver}.
+ */
+public class EntityResolverUriResolver implements URIResolver {
+
+ /** The wrapped entity resolver that is used to resolve URIs. */
+ private EntityResolver entityResolver;
+
+ /**
+ * Constructor.
+ * @param entityResolver The wrapped entity resolver that is used to resolve URIs.
+ */
+ public EntityResolverUriResolver(final EntityResolver entityResolver) {
+ this.entityResolver = entityResolver;
+ }
+
+ @Override
+ public InputSource resolveEntity(final String targetNamespace, final String schemaLocation, final String baseUri) {
+ try {
+ return entityResolver.resolveEntity(null, schemaLocation);
+ } catch (final SAXException | IOException e) {
+ return null;
+ }
+ }
+
+}
Property changes on: trunk/foray/foray-xml/src/main/java/org/foray/xml/EntityResolverUriResolver.java
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Rev
\ No newline at end of property
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java 2023-01-31 00:51:52 UTC (rev 13101)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java 2023-01-31 17:32:10 UTC (rev 13102)
@@ -33,6 +33,7 @@
import org.foray.xml.dtd.DtdElement;
import org.apache.ws.commons.schema.XmlSchemaCollection;
+import org.apache.ws.commons.schema.resolver.URIResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.event.Level;
@@ -83,7 +84,7 @@
private Dtd dtd = new Dtd();
/** The XML Schema for this document, which can be null. */
- private XmlSchemaCollection schemaCollection = new XmlSchemaCollection();
+ private XmlSchemaCollection schemaCollection;
/* Register the URLStreamHandler for classpath: URLs.
* This has to be done only once, hence a static statement. */
@@ -217,6 +218,13 @@
throws SAXException {
this.entityResolver = entityResolver;
final XMLReader xmlReader = XMLReaderFactory.createXMLReader();
+ this.schemaCollection = new XmlSchemaCollection();
+ if (entityResolver != null) {
+ final URIResolver uriResolver = new EntityResolverUriResolver(entityResolver);
+ if (uriResolver != null) {
+ this.schemaCollection.setSchemaResolver(uriResolver);
+ }
+ }
this.logger.info("Using SAX2 Parser {}", xmlReader.getClass().getName());
xmlReader.setEntityResolver(entityResolver);
xmlReader.setContentHandler(this);
@@ -431,7 +439,7 @@
&& "schemaLocation".equals(attributes.getLocalName(index))) {
final String schemaLocation = attributes.getValue(index);
final StringTokenizer tokenizer = new StringTokenizer(schemaLocation);
- /* Waste the first part. */
+ /* Discard the first token, which is the namespace part. */
tokenizer.nextToken();
final String schemaUrlString = tokenizer.nextToken();
InputStream is = null;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <vic...@us...> - 2023-01-31 00:51:54
|
Revision: 13101
http://sourceforge.net/p/foray/code/13101
Author: victormote
Date: 2023-01-31 00:51:52 +0000 (Tue, 31 Jan 2023)
Log Message:
-----------
Improvements to parsing XML schema.
Modified Paths:
--------------
trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java
Modified: trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java
===================================================================
--- trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java 2023-01-30 10:21:30 UTC (rev 13100)
+++ trunk/foray/foray-xml/src/main/java/org/foray/xml/SaxParser.java 2023-01-31 00:51:52 UTC (rev 13101)
@@ -53,6 +53,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
+import java.util.StringTokenizer;
import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
@@ -103,6 +104,9 @@
* accumulated. */
private boolean textParsingActive = true;
+ /** The entity resolver. */
+ private EntityResolver entityResolver;
+
/**
* Parses an input document and returns the object that was created.
* @param inputSource The input document.
@@ -197,7 +201,7 @@
* @param validate Indicates whether the parser should validate the document as it parses.
* @param namespaceAware Indicates whether the parser should be namespace-aware.
* @param namespacePrefixes Indicates wehther the parser should process namespace prefixes.
- * @param entityResolver Specifies the entity resolver, if any that should be used.
+ * @param entityResolver Specifies the entity resolver, if any, that should be used.
* @param notifyCharRefs Indicates whether the "notify-char-refs" feature should be turned on.
* This appears to be a Xerces-only feature.
* This feature, or something like it is <em>very</em> important for cases where we wish to pass content through
@@ -211,6 +215,7 @@
public XMLReader createSax2Parser(final boolean validate, final boolean namespaceAware,
final boolean namespacePrefixes, final EntityResolver entityResolver, final boolean notifyCharRefs)
throws SAXException {
+ this.entityResolver = entityResolver;
final XMLReader xmlReader = XMLReaderFactory.createXMLReader();
this.logger.info("Using SAX2 Parser {}", xmlReader.getClass().getName());
xmlReader.setEntityResolver(entityResolver);
@@ -424,11 +429,20 @@
for (int index = 0; index < attributes.getLength(); index ++) {
if (XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI.equals(attributes.getURI(index))
&& "schemaLocation".equals(attributes.getLocalName(index))) {
- final String schemaUrlString = attributes.getValue(index);
+ final String schemaLocation = attributes.getValue(index);
+ final StringTokenizer tokenizer = new StringTokenizer(schemaLocation);
+ /* Waste the first part. */
+ tokenizer.nextToken();
+ final String schemaUrlString = tokenizer.nextToken();
InputStream is = null;
try {
- final URL schemaUrl = new URL(schemaUrlString);
- is = schemaUrl.openStream();
+ if (this.entityResolver == null) {
+ final URL schemaUrl = new URL(schemaUrlString);
+ is = schemaUrl.openStream();
+ } else {
+ final InputSource inputSource = this.entityResolver.resolveEntity(null, schemaUrlString);
+ is = inputSource.getByteStream();
+ }
} catch (final IOException e) {
throw new SAXException(e);
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|