1 /*
2 * Copyright 2002-2009 the original author or authors.
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
17 package net.sf.json.util;
18
19 import net.sf.json.JSONArray;
20 import net.sf.json.JSONException;
21 import net.sf.json.JSONObject;
22
23 /**
24 * Base class for cycle detection in a hierarchy.<br>
25 * The JSON spec forbides cycles in a hierarchy and most parsers will raise and
26 * error when a cycle is detected. This class defines a contract for handling
27 * those cycles and two base implementations:
28 * <ul>
29 * <li>STRICT - will throw a JSONException if a cycle is found.</li>
30 * <li>LENIENT - will return an empty array or null object if a cycle is found.</li>
31 * </ul>
32 *
33 * @author Andres Almiray <aalmiray@users.sourceforge.net>
34 */
35 public abstract class CycleDetectionStrategy {
36 public static final JSONArray IGNORE_PROPERTY_ARR = new JSONArray();
37 public static final JSONObject IGNORE_PROPERTY_OBJ = new JSONObject();
38
39 /** Returns empty array and null object */
40 public static final CycleDetectionStrategy LENIENT = new LenientCycleDetectionStrategy();
41 /**
42 * Returns a special object (IGNORE_PROPERTY_OBJ) that indicates the entire
43 * property should be ignored
44 */
45 public static final CycleDetectionStrategy NOPROP = new LenientNoRefCycleDetectionStrategy();
46 /** Throws a JSONException */
47 public static final CycleDetectionStrategy STRICT = new StrictCycleDetectionStrategy();
48
49 /**
50 * Handle a repeated reference<br>
51 * Must return a valid JSONArray or null.
52 *
53 * @param reference the repeated reference.
54 */
55 public abstract JSONArray handleRepeatedReferenceAsArray( Object reference );
56
57 /**
58 * Handle a repeated reference<br>
59 * Must return a valid JSONObject or null.
60 *
61 * @param reference the repeated reference.
62 */
63 public abstract JSONObject handleRepeatedReferenceAsObject( Object reference );
64
65 private static final class LenientCycleDetectionStrategy extends CycleDetectionStrategy {
66 public JSONArray handleRepeatedReferenceAsArray( Object reference ) {
67 return new JSONArray();
68 }
69
70 public JSONObject handleRepeatedReferenceAsObject( Object reference ) {
71 return new JSONObject( true );
72 }
73 }
74
75 /**
76 * A cycle detection strategy that prevents any mention of the possible
77 * conflict from appearing.
78 *
79 * @author small
80 */
81 private static final class LenientNoRefCycleDetectionStrategy extends CycleDetectionStrategy {
82 public JSONArray handleRepeatedReferenceAsArray( Object reference ) {
83 return IGNORE_PROPERTY_ARR;
84 }
85
86 public JSONObject handleRepeatedReferenceAsObject( Object reference ) {
87 return IGNORE_PROPERTY_OBJ;
88 }
89 }
90
91 private static final class StrictCycleDetectionStrategy extends CycleDetectionStrategy {
92 public JSONArray handleRepeatedReferenceAsArray( Object reference ) {
93 throw new JSONException( "There is a cycle in the hierarchy!" );
94 }
95
96 public JSONObject handleRepeatedReferenceAsObject( Object reference ) {
97 throw new JSONException( "There is a cycle in the hierarchy!" );
98 }
99 }
100 }