KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > scriptella > configuration > ContentEl


1 /*
2  * Copyright 2006-2007 The Scriptella Project Team.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package scriptella.configuration;
17
18 import org.w3c.dom.Element JavaDoc;
19 import org.w3c.dom.Node JavaDoc;
20 import org.w3c.dom.Text JavaDoc;
21 import scriptella.spi.Resource;
22
23 import java.io.BufferedReader JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.Reader JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.List JavaDoc;
28
29
30 /**
31  * TODO: Add documentation
32  *
33  * @author Fyodor Kupolov
34  * @version 1.0
35  */

36 public class ContentEl extends XmlConfigurableBase implements Resource {
37     /**
38      * Max length of string resource to concat with the previous one.
39      * This limitation is necessary to avoid concatenation of large text blocks, because in this
40      * case too much memory is used.
41      */

42     private static final int MAX_CONCAT_RESOURCE_LENGTH = 1024 * 128; //128Kb
43
private List JavaDoc<Resource> content = new ArrayList JavaDoc<Resource>();
44     /**
45      * Null-Object to use instead of null if necessary
46      */

47     public static final Resource NULL_CONTENT = new StringResource("", "Empty Content");
48
49     public ContentEl() {
50     }
51
52     public ContentEl(XmlElement element) {
53         configure(element);
54     }
55
56     public Reader JavaDoc open() throws IOException JavaDoc {
57         if (content.isEmpty()) {
58             return NULL_CONTENT.open();
59         }
60         //If content consists of only one resource - open it
61
if (content.size() == 1) {
62             return content.get(0).open();
63         }
64         //Otherwise create a multipart reader.
65
return new BufferedReader JavaDoc(new MultipartReader());
66     }
67
68     public void configure(final XmlElement element) {
69         for (Node JavaDoc node = element.getElement().getFirstChild(); node != null; node = node.getNextSibling()) {
70             append(asResource(element, node));
71         }
72     }
73
74
75     /**
76      * Creates a resource using content from the specified node.
77      * <p>If node is not textual content or not include element, the content is skipped and null is returned.
78      *
79      * @param parentElement parent element of this node.
80      * @param node node to get content from.
81      * @return parsed resource or null.
82      */

83     static Resource asResource(final XmlElement parentElement, final Node JavaDoc node) {
84         if (node == null) {
85             return null;
86         }
87         if (node instanceof Text JavaDoc) {
88             return new StringResource(((Text JavaDoc) node).getData());
89         } else if (node instanceof Element JavaDoc && "include".equals(node.getNodeName())) {
90             return new IncludeEl(new XmlElement((Element JavaDoc) node, parentElement));
91         }
92         return null;
93
94
95     }
96
97     /**
98      * Merges this content with specified one and returns this element.
99      *
100      * @param contentEl content to merge with.
101      * @return this instance with merged content.
102      */

103     final ContentEl merge(final ContentEl contentEl) {
104         content.addAll(contentEl.content);
105         return this;
106     }
107
108     /**
109      * Appends a resource to this content.
110      *
111      * @param resource resource to append. Nulls are ignored.
112      */

113     final void append(final Resource resource) {
114         if (resource != null) {
115             //If string resource and we already have content
116
if (resource instanceof StringResource && !content.isEmpty()) {
117                 final int lastIndex = content.size() - 1;
118                 Resource last = content.get(lastIndex);
119                 if (last instanceof StringResource) { //If last resource is also a string resource
120
//Concat them and produce a new resource if new size does not exceed the memory limit
121
StringResource nextRes = (StringResource) resource;
122                     StringResource prevRes = (StringResource) last;
123                     if (prevRes.getString().length() + nextRes.getString().length() < MAX_CONCAT_RESOURCE_LENGTH) {
124                         content.set(lastIndex, new StringResource(prevRes.getString() + nextRes.getString()));
125                         return;
126                     }
127                 }
128             }
129             content.add(resource);
130         }
131     }
132
133     @Override JavaDoc
134     public String JavaDoc toString() {
135         Location loc = getLocation();
136         return loc != null ? loc.toString() : ("ContentEl{" + "content=" + content + '}');
137     }
138
139     class MultipartReader extends Reader JavaDoc {
140         private int pos = 0;
141         private Reader JavaDoc current;
142         private int blocksCount=content.size();
143
144         public int read(final char cbuf[], final int off, final int len) throws IOException JavaDoc {
145             if ((pos < 0) || ((pos >= blocksCount) && (current == null))) {
146                 return -1;
147             }
148
149             int l = len;
150             int o = off;
151
152             while (l > 0) {
153                 if (current == null) {
154                     if (pos < blocksCount) {
155                         current = content.get(pos).open();
156                         pos++;
157                     } else {
158                         return ((len - l) <= 0) ? (-1) : (len - l);
159                     }
160                 } else {
161                     final int r = current.read(cbuf, o, l);
162
163                     if (r <= 0) {
164                         current.close();
165                         current = null;
166                     } else if (r <= l) {
167                         l -= r;
168                         o += r;
169                     }
170                 }
171             }
172
173             return len - l;
174         }
175
176         public void close() throws IOException JavaDoc {
177             if (current != null) {
178                 current.close();
179                 current = null;
180             }
181
182             pos = -1;
183         }
184     }
185 }
186
Popular Tags