4 * License : The MIT License
5 * Copyright(c) 2009 olyutorskii
8 package jp.sourceforge.jovsonz;
10 import java.io.IOException;
11 import java.util.Iterator;
12 import java.util.LinkedList;
13 import java.util.List;
16 * JSON ARRAY型Valueを表す。
31 implements JsComposition<JsValue> {
33 private static final String ERRMSG_NOARRAYCOMMA =
34 "missing comma in ARRAY";
35 private static final String ERRMSG_NOELEM =
36 "missing element in ARRAY";
38 private final List<JsValue> valueList = new LinkedList<>();
39 private boolean changed = false;
50 * JSON文字列ソースからARRAY型Valueを読み込む。
52 * <p>さらに子Valueへとパース解析が進む可能性がある。
53 * 別型の可能性のある先頭文字を読み込んだ場合、
54 * ソースに文字を読み戻した後nullが返される。
56 * @param source 文字列ソース
57 * @return ARRAY型Value。別型の可能性がある場合はnull。
58 * @throws IOException 入力エラー
59 * @throws JsParseException 不正な表現または意図しない入力終了
61 static JsArray parseArray(JsonSource source)
62 throws IOException, JsParseException {
63 char charHead = source.readOrDie();
65 source.unread(charHead);
69 JsArray result = new JsArray();
72 source.skipWhiteSpace();
73 char chData = source.readOrDie();
74 if(chData == ']') break;
77 source.unread(chData);
80 throw new JsParseException(ERRMSG_NOARRAYCOMMA,
81 source.getLineNumber() );
85 JsValue value = Json.parseValue(source);
87 throw new JsParseException(ERRMSG_NOELEM,
88 source.getLineNumber() );
100 * <p>常に{@link JsTypes#ARRAY}を返す。
102 * @return {@inheritDoc}
105 public JsTypes getJsTypes(){
106 return JsTypes.ARRAY;
110 * このValueおよび子孫に変更があったか判定する。
112 * <p>子要素の追加・削除が行われたか、
113 * もしくは子要素のいずれかに変更が認められれば、
114 * このARRAY型Valueに変更があったとみなされる。
116 * @return {@inheritDoc}
119 public boolean hasChanged(){
120 if(this.changed) return true;
122 for(JsValue value : this.valueList){
123 if( ! (value instanceof JsComposition) ) continue;
124 JsComposition<?> composition = (JsComposition) value;
125 if(composition.hasChanged()) return true;
132 * このValueおよび子孫に変更がなかったことにする。
135 public void setUnchanged(){
136 this.changed = false;
138 for(JsValue value : this.valueList){
139 if( ! (value instanceof JsComposition) ) continue;
140 JsComposition<?> composition = (JsComposition) value;
141 composition.setUnchanged();
148 * 深さ優先探索を行い各種構造の出現をビジターに通知する。
150 * <p>thisを通知した後、子Valueを順に訪問し、最後に閉じ括弧を通知する。
152 * @param visitor {@inheritDoc}
153 * @throws JsVisitException {@inheritDoc}
156 public void traverse(ValueVisitor visitor) throws JsVisitException{
157 visitor.visitValue(this);
159 for(JsValue value : this.valueList){
160 value.traverse(visitor);
163 visitor.visitCompositionClose(this);
171 * @return {@inheritDoc}
175 return this.valueList.size();
181 * @return {@inheritDoc}
184 public boolean isEmpty(){
185 return this.valueList.isEmpty();
193 if(this.valueList.size() > 0) this.changed = true;
194 this.valueList.clear();
201 * <p>全ての子孫Valueのハッシュ値からその都度合成される。高コスト注意!。
203 * @return {@inheritDoc}
204 * @see java.util.List#hashCode()
207 public int hashCode(){
208 return this.valueList.hashCode();
215 * その全ての子Valueでのequals()が等価と判断された場合のみ
218 * @param obj {@inheritDoc}
219 * @return {@inheritDoc}
220 * @see java.util.List#equals(Object)
223 public boolean equals(Object obj){
224 if(this == obj) return true;
226 if( ! (obj instanceof JsArray) ) return false;
227 JsArray array = (JsArray) obj;
229 return this.valueList.equals(array.valueList);
235 * <p>同じJsValueインスタンスを複数回追加することも可能。
237 * @param value JSON Value
238 * @throws NullPointerException 引数がnull
240 public void add(JsValue value) throws NullPointerException{
241 if(value == null) throw new NullPointerException();
242 this.valueList.add(value);
248 * 配列から指定された位置のValueを返す。
250 * @param index 0で始まる配列上の位置
251 * @return Value JSON Value
252 * @throws IndexOutOfBoundsException 不正な位置指定
254 public JsValue get(int index) throws IndexOutOfBoundsException{
255 return this.valueList.get(index);
261 * <p>{@link java.util.List#remove(Object)}と異なり、
263 * {@link java.lang.Object#equals(Object)}は使われない。
265 * <p>一致するインスタンスが複数存在する場合、
266 * 先頭に近いインスタンスのみ削除される。
267 * 一致するインスタンスが存在しなければなにもしない。
269 * @param value JSON Value
270 * @return 既存のValueが削除されたならtrue
273 public boolean remove(JsValue value){
274 boolean removed = false;
276 Iterator<JsValue> it = this.valueList.iterator();
278 JsValue elem = it.next();
291 * 配列から指定位置のValueを削除する。
293 * @param index 0で始まる削除対象のインデックス値
295 * @throws IndexOutOfBoundsException 不正なインデックス値
297 public JsValue remove(int index) throws IndexOutOfBoundsException{
298 JsValue removed = this.valueList.remove(index);
304 * Valueにアクセスするための反復子を提供する。
306 * <p>この反復子での削除作業はできない。
312 public Iterator<JsValue> iterator(){
313 return UnmodIterator.unmodIterator(this.valueList);
321 * <p>JSON表記の全体もしくは一部としての利用も可能。
323 * @return {@inheritDoc}
326 public String toString(){
327 StringBuilder text = new StringBuilder();
330 boolean hasElem = false;
331 for(JsValue value : this.valueList){
332 if(hasElem) text.append(',');
338 return text.toString();