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: bommel $)
27   * @version $Revision: 1187700 $ $Date: 2011-10-22 07:19:37 -0500 (Sat, 22 Oct 2011) $
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              // Close the <insert> element, if any.
66              //error close the last op if any
67              endInsert();
68              
69              _wrapped.endElement ("changes");
70              
71              hasChanges = false;
72          }
73          
74          _wrapped.endElement ("partial-response");
75      }
76  
77      public void endError() throws IOException
78      {
79          // Close open <error-message> element.
80          
81          _wrapped.endCDATA();
82          _wrapped.endElement ("error-message");
83          _wrapped.endElement ("error");
84      }
85  
86      public void endEval() throws IOException
87      {
88          // Close open <eval> element.
89          
90          _wrapped.endCDATA();
91          _wrapped.endElement ("eval");
92      }
93  
94      public void endExtension() throws IOException
95      {
96          _wrapped.endElement ("extension");
97      }
98  
99      public void endInsert() throws IOException
100     {
101         if (insertType == null) {
102             // No insert started; ignore.
103             
104             return;
105         }
106         
107         // Close open <insert> element.
108         
109         _wrapped.endCDATA();
110         _wrapped.endElement (insertType);
111         _wrapped.endElement ("insert");
112         
113         insertType = null;
114     }
115 
116     public void endUpdate() throws IOException
117     {
118         _wrapped.endCDATA();
119         _wrapped.endElement ("update");
120     }
121 
122     /**
123      * {@inheritDoc}
124      */
125     @Override
126     public ResponseWriter getWrapped()
127     {
128         return _wrapped;
129     }
130 
131     public void redirect(String url) throws IOException
132     {
133         _wrapped.startElement ("redirect", null);
134         _wrapped.writeAttribute ("url", url, null);
135         _wrapped.endElement ("redirect");
136     }
137 
138     /**
139      * {@inheritDoc}
140      */
141     @Override
142     public void startDocument() throws IOException
143     {
144         _wrapped.write ("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
145         
146         _wrapped.startElement ("partial-response", null);
147     }
148 
149     public void startError(String errorName) throws IOException
150     {
151         _wrapped.startElement ("error", null);
152         
153         _wrapped.startElement ("error-name", null);
154         _wrapped.write (errorName);
155         _wrapped.endElement ("error-name");
156         
157         _wrapped.startElement ("error-message", null);
158         startCDATA();
159         
160         // Leave open; caller will write message.
161     }
162 
163     @Override
164     public void startCDATA() throws IOException {
165         _wrapped.startCDATA();
166     }
167 
168     @Override
169     public void endCDATA() throws IOException {
170         _wrapped.endCDATA();    
171     }
172 
173     public void startEval() throws IOException
174     {
175         startChanges();
176         
177         _wrapped.startElement ("eval", null);
178         startCDATA();
179         
180         // Leave open; caller will write statements.
181     }
182 
183     public void startExtension(Map<String, String> attributes) throws IOException
184     {
185         Iterator<String> attrNames;
186         
187         startChanges();
188         
189         _wrapped.startElement ("extension", null);
190         
191         // Write out extension attributes.
192         // TODO: schema mentions "id" attribute; not used?
193         
194         attrNames = attributes.keySet().iterator();
195         
196         while (attrNames.hasNext()) {
197             String attrName = attrNames.next();
198             
199             _wrapped.writeAttribute (attrName, attributes.get (attrName), null);
200         }
201         
202         // Leave open; caller will write extension elements.
203     }
204 
205     public void startInsertAfter(String targetId) throws IOException
206     {
207         startInsertCommon ("after", targetId);
208     }
209 
210     public void startInsertBefore(String targetId) throws IOException
211     {
212         startInsertCommon ("before", targetId);
213     }
214 
215     public void startUpdate(String targetId) throws IOException
216     {
217         startChanges();
218         
219         _wrapped.startElement ("update", null);
220         _wrapped.writeAttribute ("id", targetId, null);
221         startCDATA();
222         
223         // Leave open; caller will write content.
224     }
225 
226     public void updateAttributes(String targetId, Map<String, String> attributes) throws IOException
227     {
228         Iterator<String> attrNames;
229         
230         startChanges();
231         
232         _wrapped.startElement ("attributes", null);
233         _wrapped.writeAttribute ("id", targetId, null);
234         
235         attrNames = attributes.keySet().iterator();
236         
237         while (attrNames.hasNext()) {
238             String attrName = attrNames.next();
239             
240             _wrapped.startElement ("attribute", null);
241             _wrapped.writeAttribute ("name", attrName, null);
242             _wrapped.writeAttribute ("value", attributes.get (attrName), null);
243             _wrapped.endElement ("attribute");
244         }
245         
246         _wrapped.endElement ("attributes");
247     }
248     
249     private void startChanges () throws IOException {
250         if (!hasChanges) {
251             _wrapped.startElement ("changes", null);
252             
253             hasChanges = true;
254         }
255     }
256     
257     private void startInsertCommon (String type, String targetId) throws IOException {
258         if (insertType != null) {
259             // An insert has already been started; ignore.
260             
261             return;
262         }
263         
264         insertType = type;
265         
266         startChanges();
267         
268         _wrapped.startElement ("insert", null);
269         _wrapped.startElement (insertType, null);
270         _wrapped.writeAttribute ("id", targetId, null);
271         startCDATA();
272         
273         // Leave open; caller will write content.
274     }
275 }