View Javadoc

1   package org.springframework.web.servlet.view.json.writer.sojo;
2   
3   import java.beans.PropertyEditor;
4   import java.util.Date;
5   
6   import net.sf.sojo.common.WalkerInterceptor;
7   import net.sf.sojo.core.Constants;
8   import net.sf.sojo.core.UniqueIdGenerator;
9   import net.sf.sojo.interchange.SerializerException;
10  import net.sf.sojo.util.Util;
11  
12  import org.springframework.beans.PropertyEditorRegistry;
13  import org.springframework.web.servlet.view.json.JsonStringWriter;
14  
15  public class JsonViewWalkerInterceptor implements WalkerInterceptor {
16  	
17  
18  	private StringBuffer jsonString = new StringBuffer();
19  	private boolean ignoreNullValues = true;
20  	private PropertyEditorRegistry propertyEditorRegistry;
21  	private String objectName;
22  	private boolean convertAllMapValues;
23  	private String keepValueTypesMode;
24  	
25  	public String getJsonString() {
26  		return jsonString.toString();
27  	}
28  
29  	public boolean getIgnoreNullValues() {
30  		return ignoreNullValues;
31  	}
32  
33  	public void setIgnoreNullValues(boolean ignoreNullValues) {
34  		this.ignoreNullValues = ignoreNullValues;
35  	}
36  
37  	public void startWalk(Object pvStartObject) {
38  		jsonString = new StringBuffer();
39  	}
40  
41  	public void endWalk() {
42  		Util.delLastComma(jsonString);
43  	}
44  
45  	/**
46  	 * Convert escape (control) character from a JSON representation in a Java-String.
47  	 * This means: <code>\\b</code> to <code>\b</code>
48  	 * @param pvValue
49  	 * @return converted String
50  	 */
51  	public static String handleControlCharacterBack(final String pvValue) {
52  
53  		if (pvValue == null) {
54  			return null;
55  		}
56  		StringBuffer sb = new StringBuffer();
57  		int l = pvValue.length();
58  		char c;
59  		for (int i=0; i<l; i++) {
60  			c = pvValue.charAt(i);
61              switch (c) {
62  	            case 0:
63  	            	break;
64  	            case '\n':
65  	            case '\r':
66  	            case '\t':
67  	            	sb.append(c);
68  	            	break;
69  	            case '\\':
70  	                i++;
71  					c = pvValue.charAt(i);
72  	                switch (c) {
73  		                case 'b':
74  		                    sb.append('\b');
75  		                    break;
76  		                case 't':
77  		                    sb.append('\t');
78  		                    break;
79  		                case 'n':
80  		                    sb.append('\n');
81  		                    break;
82  		                case 'f':
83  		                    sb.append('\f');
84  		                    break;
85  		                case 'r':
86  		                    sb.append('\r');
87  		                    break;
88  //		                case 'u':
89  //		                    sb.append((char)Integer.parseInt(next(4), 16));
90  //		                    break;
91  //		                case 'x' :
92  //		                    sb.append((char) Integer.parseInt(next(2), 16));
93  //		                    break;
94  		                default:
95  		                    sb.append(c);
96  		                }
97  	                break;
98  	            default:
99  	                sb.append(c);
100 	            }
101         }
102 		return sb.toString();
103 	}
104 
105 	/**
106 	 * Convert escape (control) character to a JSON representation.
107 	 * This means: <code>\b</code> to <code>\\b</code>
108 	 * @param pvValue
109 	 * @return converted String
110 	 */
111 	public static Object handleControlCharacter(final Object pvValue) {
112 		Object lvReturn = pvValue;
113 		if (lvReturn != null && lvReturn.getClass().equals(String.class)) {
114 			String lvString = lvReturn.toString();
115 
116 	        int len = lvString.length();
117 			/*if (len == 0) {
118 				return "\"\"";
119 			}*/
120 	
121 	        char vorgChar;
122 	        char c = 0;
123 	        StringBuffer sb = new StringBuffer(len + 4);
124 	
125 	        for (int i = 0; i < len; i++) {
126 	            vorgChar = c;
127 	            c = lvString.charAt(i);
128 	            switch (c) {
129 		            case '\\':
130 		                    sb.append("\\\\");
131 		                break;
132 		            case '"':
133 		                sb.append('\\').append(c);
134 		                break;
135 		            case '/':
136 		                sb.append('\\').append(c);
137 		                break;
138 		            case '\b':
139 		                sb.append("\\b");
140 		                break;
141 		            case '\t':
142 		                sb.append("\\t");
143 		                break;
144 		            case '\n':
145 		                sb.append("\\n");
146 		                break;
147 		            case '\f':
148 		                sb.append("\\f");
149 		                break;
150 		            case '\r':
151 		                sb.append("\\r");
152 		                break;
153 		            default:
154 //		                if (c < ' ' || (c >= '\u0080' && c < '\u00a0') || (c >= '\u2000' && c < '\u2100')) {
155 //		                    hex = "000" + Integer.toHexString(c);
156 //		                    sb.append("\\u" + hex.substring(hex.length() - 4));
157 //		                } else {
158 		                    sb.append(c);
159 //		                }
160 		            }
161 	        }
162 	        return sb.toString();
163 		} else {
164 			return lvReturn;
165 		}
166 	}
167 	
168 	public String handleSimpleJsonValue(Object pvValue, String path){
169     	Object convertedValue = convertJsonValue(pvValue, path);
170     	return handleJsonValue (convertedValue );
171     }
172     
173     public  String handleJsonValue (Object pvValue) {
174     	String s = "";
175     	if (pvValue != null) {
176 	    	Object o = handleControlCharacter(pvValue);
177 	    	s = object2StringWithDoubleQuote(o);
178     	}
179     	return s;
180     }
181     
182     public String object2StringWithDoubleQuote(Object pvObject) {
183     	StringBuffer s = new StringBuffer("");
184     	if(JsonStringWriter.MODE_KEEP_VALUETYPES_BOOLEANS.equals(keepValueTypesMode)){
185     		if(pvObject.getClass().equals(Boolean.class))
186     			s.append(pvObject);
187     		else
188     			s.append("\"").append(pvObject).append("\"");
189     	}else if(JsonStringWriter.MODE_KEEP_VALUETYPES_ALL.equals(keepValueTypesMode)){
190     	   	if (pvObject.getClass().equals(String.class) || pvObject.getClass().equals(Character.class) || Date.class.isAssignableFrom(pvObject.getClass())) {
191 	    		s.append("\"").append(pvObject).append("\"");
192 	    	}else  {
193 	    		s.append(pvObject);
194 	    	}
195     	}else
196     		s.append("\"").append(pvObject).append("\"");
197     		
198     	return s.toString();
199     }
200     
201     
202 
203     private Object convertJsonValue(Object pvValue, String path) {
204     	if(path != null && propertyEditorRegistry != null && (convertAllMapValues || path.startsWith("("+ objectName + ")."))){
205 	    	String p = path.replaceAll("^\\("+ objectName + "\\).","").replaceAll("\\).\\[","\\)\\[");
206 	    	PropertyEditor  ce = propertyEditorRegistry.findCustomEditor(pvValue.getClass(), p);
207 			if(ce == null)
208 				return pvValue;
209 			else{
210 				ce.setValue(pvValue);
211 				return ce.getAsText();
212 			}
213 				
214     	}else
215     		return pvValue;
216 	}
217 
218 	
219     
220 	public boolean visitElement(Object pvKey, int pvIndex, Object pvValue, int pvType, String pvPath, int pvNumberOfRecursion) {
221 		// --- SIMPLE ---
222 		if ( pvPath.indexOf("class") >= 0 || pvPath.indexOf(UniqueIdGenerator.UNIQUE_ID_PROPERTY) >= 0) {
223 			return false;
224 		} 
225 		if (pvType == Constants.TYPE_SIMPLE) {
226 			if (pvKey != null && pvKey.getClass().equals(String.class)) {
227 				jsonString.append(handleJsonValue(pvKey)).append(":");
228 			}  else if (pvKey != null) {
229 				throw new SerializerException("JSON support only properties/keys from type String and not: '" + pvKey.getClass().getName() + "' (" + pvKey + ")");
230 			}
231 			jsonString.append(handleSimpleJsonValue(pvValue, pvPath)).append(",");
232 		} 
233 		
234 		// --- NULL ---
235 		else if (pvType == Constants.TYPE_NULL) {
236 			if("".equals(pvPath))
237 				jsonString.append("null");
238 			else if (!getIgnoreNullValues()) {
239 					jsonString.append(handleJsonValue(pvKey)).append(":null,");
240 			}
241 		}
242 		
243 		// -- KEY and not SIMPLE ---
244 		else if (pvKey != null && pvValue != null) {
245 			if (pvKey != null && pvKey.getClass().equals(String.class)) {
246 				jsonString.append(handleJsonValue(pvKey)).append(":");
247 			} else {
248 				throw new SerializerException("JSON support only properties/keys from type String and not: '" + pvKey.getClass().getName() + "' (" + pvKey + ")");
249 			}
250 		}
251 		
252 		return false;
253 	}
254 	
255 
256 	public void visitIterateableElement(Object pvValue, int pvType, String pvPath, int pvBeginEnd) {
257 		
258 		if (pvBeginEnd == Constants.ITERATOR_BEGIN) {
259 			
260 			if (pvType == Constants.TYPE_ITERATEABLE) {
261 					//if(!pvPath.endsWith("."))
262 						jsonString.append("[");
263 				} else if (pvType == Constants.TYPE_MAP) {
264 					jsonString.append("{");
265 				}
266 		} else if (pvBeginEnd == Constants.ITERATOR_END) {
267 				Util.delLastComma(jsonString);
268 				if (pvType == Constants.TYPE_ITERATEABLE) {
269 					jsonString.append("],");
270 				} else if (pvType == Constants.TYPE_MAP) {					
271 					jsonString.append("},");
272 				}
273 		}
274 	}
275 	
276 
277 	public void setPropertyEditorRegistry(
278 			PropertyEditorRegistry propertyEditorRegistry) {
279 		this.propertyEditorRegistry = propertyEditorRegistry;
280 	}
281 
282 	public void setObjectName(String objectName) {
283 		this.objectName = objectName;
284 	}
285 
286 	public void setConvertAllMapValues(boolean convertAllMapValues) {
287 		this.convertAllMapValues = convertAllMapValues;
288 	}
289 
290 	public void setKeepValueTypesMode(String keepValueTypesMode) {
291 		this.keepValueTypesMode = keepValueTypesMode;
292 	}
293 
294 	
295     
296 	
297 	
298 	
299 	
300 	
301 }