You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by br...@apache.org on 2004/09/02 12:05:34 UTC
svn commit: rev 37365 - cocoon/trunk/src/java/org/apache/cocoon/xml
Author: bruno
Date: Thu Sep 2 03:05:32 2004
New Revision: 37365
Modified:
cocoon/trunk/src/java/org/apache/cocoon/xml/ParamSaxBuffer.java
Log:
Handle processing parameters in case text is split over multiple
character events (a not so rare occasion it seems, I had it with
the default CForms resource bundles). The processing now doesn't
happen directly in the characters call anymore but in a method
processParams() that must be called after the buffer is filled.
Modified: cocoon/trunk/src/java/org/apache/cocoon/xml/ParamSaxBuffer.java
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/xml/ParamSaxBuffer.java (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/xml/ParamSaxBuffer.java Thu Sep 2 03:05:32 2004
@@ -17,6 +17,8 @@
import java.util.Iterator;
import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
import java.io.Writer;
import java.io.IOException;
@@ -26,12 +28,15 @@
/**
* Modification of the SAX buffer with parameterization capabilities.
*
- * Any <code>{name}</code> expression inside of the character events can be
+ * <p>Any <code>{name}</code> expression inside of the character events can be
* replaced by the content of another SaxBuffer if it is present in the map
* passed to the {@link #toSAX(ContentHandler, Map)} method.
*
+ * <p>Once all events have been pushed into this buffer, you need to call
+ * {@link #processParams()}.
+ *
* @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
- * @version CVS $Id: ParamSaxBuffer.java,v 1.7 2004/07/06 22:38:28 vgritsenko Exp $
+ * @version CVS $Id$
*/
public class ParamSaxBuffer extends SaxBuffer {
@@ -49,45 +54,102 @@
}
/**
- * Parses text and extracts <code>{name}</code> parameters for later
+ * Parses text in character events and extracts <code>{name}</code> parameters for later
* substitution.
- *
- * FIXME: This method throws exception when '{' and '}' are separated onto two character events
*/
- public void characters(char ch[], int start, int length) throws SAXException {
- final int end = start + length;
- for (int i = start; i < end; i++) {
- if (ch[i] == '{') {
- // Send any collected characters so far
- if (i > start) {
- addBit(new Characters(ch, start, i - start));
+ public void processParams() throws SAXException {
+ // what we do here is running over all sax bits and copying them over
+ // into a new list, and meanwhile processing all Character bits
+
+ int initialSize;
+ if (saxbits.size() <= 3)
+ initialSize = 6;
+ else
+ initialSize = (int)((double)saxbits.size() * 1.35d);
+
+ List newSaxBits = new ArrayList(initialSize);
+
+ int i = 0;
+ while (i < saxbits.size()) {
+ Object bit = saxbits.get(i);
+ if (bit instanceof Characters) {
+ char[] chars = ((Characters)bit).ch;
+
+ // check if there are more character events immediately following this one,
+ // if so merge all data into one big array
+ int consecutiveCharacterEventCount = 0;
+ int totalLength = chars.length;
+ for (int k = i + 1; k < saxbits.size(); k++) {
+ Object otherbit = saxbits.get(k);
+ if (otherbit instanceof Characters) {
+ consecutiveCharacterEventCount++;
+ totalLength += ((Characters)otherbit).ch.length;
+ } else {
+ break;
+ }
}
- // Find closing brace, and construct parameter name
- StringBuffer name = new StringBuffer();
- int j = i + 1;
- for (; j < end; j++) {
- if (ch[j] == '}') {
- break;
+ if (consecutiveCharacterEventCount > 0) {
+ char[] newchars = new char[totalLength];
+ System.arraycopy(chars, 0, newchars, 0, chars.length);
+ int newCharPos = chars.length;
+ for (int k = 0; k < consecutiveCharacterEventCount; k++) {
+ Object otherbit = saxbits.get(i + 1 + k);
+ char[] otherchars = ((Characters)otherbit).ch;
+ System.arraycopy(otherchars, 0, newchars, newCharPos, otherchars.length);
+ newCharPos += otherchars.length;
}
- name.append(ch[j]);
+ chars = newchars;
+ i += consecutiveCharacterEventCount + 1;
+ } else {
+ i++;
}
- if (j == end) {
- throw new SAXException("Unclosed '}'");
+
+ // now process the actual {...}
+ int start = 0;
+ final int end = chars.length;
+ for (int r = 0; r < end; r++) {
+ if (chars[r] == '{') {
+ // Send any collected characters so far
+ if (r > start) {
+ newSaxBits.add(new Characters(chars, start, r - start));
+ }
+
+ // Find closing brace, and construct parameter name
+ StringBuffer name = new StringBuffer();
+ int j = r + 1;
+ for (; j < end; j++) {
+ if (chars[j] == '}') {
+ break;
+ }
+ name.append(chars[j]);
+ }
+ if (j == end) {
+ throw new SAXException("Unclosed '}'");
+ }
+ newSaxBits.add(new Parameter(name.toString()));
+
+ // Continue processing
+ r = j;
+ start = j + 1;
+ continue;
+ }
}
- addBit(new Parameter(name.toString()));
- // Continue processing
- i = j;
- start = j + 1;
- continue;
+ // Send any tailing characters
+ if (start < end) {
+ newSaxBits.add(new Characters(chars, start, end - start));
+ }
+ } else {
+ newSaxBits.add(bit);
+ i++;
}
}
+ this.saxbits = newSaxBits;
+ }
- // Send any tailing characters
- if (start < end) {
- addBit(new Characters(ch, start, end - start));
- }
+ public void characters(char ch[], int start, int length) throws SAXException {
+ addBit(new Characters(ch, start, length));
}
/**