View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package javax.faces.context;
20  
21  import java.io.IOException;
22  import java.util.Iterator;
23  import java.util.Map;
24  
25  /**
26   * @author Simon Lessard (latest modification by $Author: lu4242 $)
27   * @version $Revision: 1401352 $ $Date: 2012-10-23 12:16:45 -0500 (Tue, 23 Oct 2012) $
28   * 
29   * @since 2.0
30   */
31  public class PartialResponseWriter extends ResponseWriterWrapper
32  {
33      public static final String RENDER_ALL_MARKER = "javax.faces.ViewRoot";
34      public static final String VIEW_STATE_MARKER = "javax.faces.ViewState";
35  
36      private ResponseWriter _wrapped;
37      private boolean hasChanges;
38      private String insertType;
39  
40     
41      /**
42       * 
43       */
44      public PartialResponseWriter(ResponseWriter writer)
45      {
46          _wrapped = writer;
47      }
48  
49      public void delete(String targetId) throws IOException
50      {
51          startChanges();
52          
53          _wrapped.startElement ("delete", null);
54          _wrapped.writeAttribute ("id", targetId, null);
55          _wrapped.endElement ("delete");
56      }
57  
58      /**
59       * {@inheritDoc}
60       */
61      @Override
62      public void endDocument() throws IOException
63      {
64          if (hasChanges)
65          {
66              // Close the <insert> element, if any.
67              //error close the last op if any
68              endInsert();
69              
70              _wrapped.endElement ("changes");
71              
72              hasChanges = false;
73          }
74          
75          _wrapped.endElement ("partial-response");
76      }
77  
78      public void endError() throws IOException
79      {
80          // Close open <error-message> element.
81          
82          _wrapped.endCDATA();
83          _wrapped.endElement ("error-message");
84          _wrapped.endElement ("error");
85      }
86  
87      public void endEval() throws IOException
88      {
89          // Close open <eval> element.
90          
91          _wrapped.endCDATA();
92          _wrapped.endElement ("eval");
93      }
94  
95      public void endExtension() throws IOException
96      {
97          _wrapped.endElement ("extension");
98      }
99  
100     public void endInsert() throws IOException
101     {
102         if (insertType == null)
103         {
104             // No insert started; ignore.
105             
106             return;
107         }
108         
109         // Close open <insert> element.
110         
111         _wrapped.endCDATA();
112         _wrapped.endElement (insertType);
113         _wrapped.endElement ("insert");
114         
115         insertType = null;
116     }
117 
118     public void endUpdate() throws IOException
119     {
120         _wrapped.endCDATA();
121         _wrapped.endElement ("update");
122     }
123 
124     /**
125      * {@inheritDoc}
126      */
127     @Override
128     public ResponseWriter getWrapped()
129     {
130         return _wrapped;
131     }
132 
133     public void redirect(String url) throws IOException
134     {
135         _wrapped.startElement ("redirect", null);
136         _wrapped.writeAttribute ("url", url, null);
137         _wrapped.endElement ("redirect");
138     }
139 
140     /**
141      * {@inheritDoc}
142      */
143     @Override
144     public void startDocument() throws IOException
145     {
146         _wrapped.write ("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
147         
148         _wrapped.startElement ("partial-response", null);
149         
150         // If by some reason the response has been reset, and the same
151         // PartialResponseWriter is used, it is necessary to ensure any 
152         // variable is initialized in a consistent state. To do that,
153         // the best point is when the document is started.
154         hasChanges = false;
155         insertType = null;
156     }
157 
158     public void startError(String errorName) throws IOException
159     {
160         _wrapped.startElement ("error", null);
161         
162         _wrapped.startElement ("error-name", null);
163         _wrapped.write (errorName);
164         _wrapped.endElement ("error-name");
165         
166         _wrapped.startElement ("error-message", null);
167         startCDATA();
168         
169         // Leave open; caller will write message.
170     }
171 
172     @Override
173     public void startCDATA() throws IOException
174     {
175         _wrapped.startCDATA();
176     }
177 
178     @Override
179     public void endCDATA() throws IOException
180     {
181         _wrapped.endCDATA();    
182     }
183 
184     public void startEval() throws IOException
185     {
186         startChanges();
187         
188         _wrapped.startElement ("eval", null);
189         startCDATA();
190         
191         // Leave open; caller will write statements.
192     }
193 
194     public void startExtension(Map<String, String> attributes) throws IOException
195     {
196         Iterator<String> attrNames;
197         
198         startChanges();
199         
200         _wrapped.startElement ("extension", null);
201         
202         // Write out extension attributes.
203         // TODO: schema mentions "id" attribute; not used?
204         
205         attrNames = attributes.keySet().iterator();
206         
207         while (attrNames.hasNext())
208         {
209             String attrName = attrNames.next();
210             
211             _wrapped.writeAttribute (attrName, attributes.get (attrName), null);
212         }
213         
214         // Leave open; caller will write extension elements.
215     }
216 
217     public void startInsertAfter(String targetId) throws IOException
218     {
219         startInsertCommon ("after", targetId);
220     }
221 
222     public void startInsertBefore(String targetId) throws IOException
223     {
224         startInsertCommon ("before", targetId);
225     }
226 
227     public void startUpdate(String targetId) throws IOException
228     {
229         startChanges();
230         
231         _wrapped.startElement ("update", null);
232         _wrapped.writeAttribute ("id", targetId, null);
233         startCDATA();
234         
235         // Leave open; caller will write content.
236     }
237 
238     public void updateAttributes(String targetId, Map<String, String> attributes) throws IOException
239     {
240         Iterator<String> attrNames;
241         
242         startChanges();
243         
244         _wrapped.startElement ("attributes", null);
245         _wrapped.writeAttribute ("id", targetId, null);
246         
247         attrNames = attributes.keySet().iterator();
248         
249         while (attrNames.hasNext())
250         {
251             String attrName = attrNames.next();
252             
253             _wrapped.startElement ("attribute", null);
254             _wrapped.writeAttribute ("name", attrName, null);
255             _wrapped.writeAttribute ("value", attributes.get (attrName), null);
256             _wrapped.endElement ("attribute");
257         }
258         
259         _wrapped.endElement ("attributes");
260     }
261     
262     private void startChanges () throws IOException
263     {
264         if (!hasChanges)
265         {
266             _wrapped.startElement ("changes", null);
267             
268             hasChanges = true;
269         }
270     }
271     
272     private void startInsertCommon (String type, String targetId) throws IOException
273     {
274         if (insertType != null)
275         {
276             // An insert has already been started; ignore.
277             
278             return;
279         }
280         
281         insertType = type;
282         
283         startChanges();
284         
285         _wrapped.startElement ("insert", null);
286         _wrapped.startElement (insertType, null);
287         _wrapped.writeAttribute ("id", targetId, null);
288         startCDATA();
289         
290         // Leave open; caller will write content.
291     }
292 }