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を表す。
28 implements JsComposition<JsValue> {
30 private static final String ERRMSG_NOARRAYCOMMA =
31 "missing comma in ARRAY";
32 private static final String ERRMSG_NOELEM =
33 "missing element in ARRAY";
35 private final List<JsValue> valueList = new LinkedList<JsValue>();
36 private boolean changed = false;
47 * JSON文字列ソースからARRAY型Valueを読み込む。
48 * さらに子Valueへとパース解析が進む可能性がある。
49 * 別型の可能性のある先頭文字を読み込んだ場合、
50 * ソースに文字を読み戻した後nullが返される。
51 * @param source 文字列ソース
52 * @return ARRAY型Value。別型の可能性がある場合はnull。
53 * @throws IOException 入力エラー
54 * @throws JsParseException 不正な表現または意図しない入力終了
56 static JsArray parseArray(JsonSource source)
57 throws IOException, JsParseException {
58 char charHead = source.readOrDie();
60 source.unread(charHead);
64 JsArray result = new JsArray();
67 source.skipWhiteSpace();
68 char chData = source.readOrDie();
69 if(chData == ']') break;
72 source.unread(chData);
75 throw new JsParseException(ERRMSG_NOARRAYCOMMA,
76 source.getLineNumber() );
80 JsValue value = Json.parseValue(source);
82 throw new JsParseException(ERRMSG_NOELEM,
83 source.getLineNumber() );
94 * 常に{@link JsTypes#ARRAY}を返す。
95 * @return {@inheritDoc}
98 public JsTypes getJsTypes(){
103 * このValueおよび子孫に変更があったか判定する。
105 * もしくは子要素のいずれかに変更が認められれば、
106 * このARRAY型Valueに変更があったとみなされる。
107 * @return {@inheritDoc}
110 public boolean hasChanged(){
111 if(this.changed) return true;
113 for(JsValue value : this.valueList){
114 if( ! (value instanceof JsComposition) ) continue;
115 JsComposition composition = (JsComposition) value;
116 if(composition.hasChanged()) return true;
123 * このValueおよび子孫に変更がなかったことにする。
126 public void setUnchanged(){
127 this.changed = false;
129 for(JsValue value : this.valueList){
130 if( ! (value instanceof JsComposition) ) continue;
131 JsComposition composition = (JsComposition) value;
132 composition.setUnchanged();
139 * 深さ優先探索を行い各種構造の出現をビジターに通知する。
140 * thisを通知した後、子Valueを順に訪問し、最後に閉じ括弧を通知する。
141 * @param visitor {@inheritDoc}
142 * @throws JsVisitException {@inheritDoc}
145 public void traverse(ValueVisitor visitor) throws JsVisitException{
146 visitor.visitValue(this);
148 for(JsValue value : this.valueList){
149 value.traverse(visitor);
152 visitor.visitCompositionClose(this);
159 * @return {@inheritDoc}
163 return this.valueList.size();
168 * @return {@inheritDoc}
171 public boolean isEmpty(){
172 return this.valueList.isEmpty();
180 if(this.valueList.size() > 0) this.changed = true;
181 this.valueList.clear();
187 * 全ての子孫Valueのハッシュ値からその都度合成される。高コスト注意!。
188 * @return {@inheritDoc}
189 * @see java.util.List#hashCode()
192 public int hashCode(){
193 return this.valueList.hashCode();
199 * その全ての子Valueでのequals()が等価と判断された場合のみ
201 * @param obj {@inheritDoc}
202 * @return {@inheritDoc}
203 * @see java.util.List#equals(Object)
206 public boolean equals(Object obj){
207 if(this == obj) return true;
209 if( ! (obj instanceof JsArray) ) return false;
210 JsArray array = (JsArray) obj;
212 return this.valueList.equals(array.valueList);
217 * 同じJsValueインスタンスを複数回追加することも可能。
218 * @param value JSON Value
219 * @throws NullPointerException 引数がnull
221 public void add(JsValue value) throws NullPointerException{
222 if(value == null) throw new NullPointerException();
223 this.valueList.add(value);
229 * 配列から指定された位置のValueを返す。
230 * @param index 0で始まる配列上の位置
231 * @return Value JSON Value
232 * @throws IndexOutOfBoundsException 不正な位置指定
234 public JsValue get(int index) throws IndexOutOfBoundsException{
235 return this.valueList.get(index);
240 * {@link java.util.List#remove(Object)}と異なり、
242 * {@link java.lang.Object#equals(Object)}は使われない。
243 * 一致するインスタンスが複数存在する場合、
244 * 先頭に近いインスタンスのみ削除される。
245 * 一致するインスタンスが存在しなければなにもしない。
246 * @param value JSON Value
247 * @return 既存のValueが削除されたならtrue
250 public boolean remove(JsValue value){
251 boolean removed = false;
253 Iterator<JsValue> it = this.valueList.iterator();
255 JsValue elem = it.next();
268 * 配列から指定位置のValueを削除する。
269 * @param index 0で始まる削除対象のインデックス値
271 * @throws IndexOutOfBoundsException 不正なインデックス値
273 public JsValue remove(int index) throws IndexOutOfBoundsException{
274 JsValue removed = this.valueList.remove(index);
280 * Valueにアクセスするための反復子を提供する。
285 public Iterator<JsValue> iterator(){
286 return UnmodIterator.unmodIterator(this.valueList);
292 * JSON表記の全体もしくは一部としての利用も可能。
293 * @return {@inheritDoc}
296 public String toString(){
297 StringBuilder text = new StringBuilder();
300 boolean hasElem = false;
301 for(JsValue value : this.valueList){
302 if(hasElem) text.append(',');
308 return text.toString();