/*
 * Resource class.
 *
 * Copyright (C) 2007 SATOH Takayuki All Rights Reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package ts.util.resource;

import java.util.List;
import java.util.ArrayList;

/**
 * リソースクラス。
 * <br>
 * キーと値の対応を保持するクラスのインターフェイス。
 * キーを指定して値を取得したり、設定したりするためのメソッドを宣言している。
 * <br>
 * キーは、階層構造を持った文字列であり、各階層にあたる「要素」と同じ階層にある
 * 複数の要素を識別するための「属性」により構成される。
 * 要素の区切り文字を<code>.</code>（ピリオド）とし、属性を<code>()</code>で
 * 囲むとした場合、キーの形式は次のようになる：
 * <pre>
 *     &lt;要素1&gt;.&lt;要素2&gt;.&lt;要素3&gt;(&lt;属性1&gt;=&lt;値1&gt;,&lt;属性2&gt;=&lt;値2&gt;).&lt;要素4&gt;.…
 * </pre>
 *
 * @author  佐藤隆之. 
 * @version $Revision: 1.2 $, $Date: 2010-11-14 11:51:02 $
 */
public interface Resource
{
  /**
   * 基底要素の名前を取得する。
   *
   * @return 基底要素の名前。
   */
  String getBaseElementName();

  /**
   * 指定されたキーに最初に該当する要素の値文字列を取得する。
   * <br>
   * 該当する要素が存在しない場合は空文字列を返す。
   * 引数のキーが不正な場合は例外をスローする。
   *
   * @param  key キー文字列。
   * @return 引数のキーに最初に該当する要素の値文字列。
   * @throws IllegalKeyException キーが不正な場合。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   */
  String getFirstValue(String key) throws IllegalKeyException;

  /**
   * 指定されたキーに該当する全要素の値文字列のリストを取得する。
   * <br>
   * 該当する要素が一つも存在しない場合は空のリストを返す。
   * 引数のキーが不正な場合は例外をスローする。
   *
   * @param  key キー文字列。
   * @return 引数のキーに該当する全要素の値文字列のリスト。
   * @throws IllegalKeyException キーが不正な場合。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   */
  List<String> getValues(String key) throws IllegalKeyException;

  /**
   * 指定されたキーに最初に該当する要素の、指定された属性の値を取得する。
   * <br>
   * 該当する要素が存在しない場合は空文字列を返す。
   * 該当する要素に、指定された名前の属性が存在しない場合は空文字列を返す。
   * 引数のキーが不正な場合は例外をスローする。
   *
   * @param  key キー文字列。
   * @param  attr 属性名。
   * @return 引数のキーに最初に該当する要素の、指定された属性の値。
   * @throws IllegalKeyException キーが不正な場合。
   * @throws AssertError 引数がヌルの場合（デバッグモードのみ）。
   */
  String getFirstAttribute(String key, String attr) throws IllegalKeyException;

  /**
   * 指定されたキーに該当する全要素の、指定された属性の値のリストを取得する。
   * <br>
   * 該当する要素が一つも存在しない場合は空のリストを返す。
   * 引数のキーが不正な場合は例外をスローする。
   *
   * @param  key キー文字列。
   * @param  attr 属性名。
   * @return 引数のキーに該当する全要素の、指定された属性の値のリスト。
   * @throws IllegalKeyException キーが不正な場合。
   * @throws AssertError 引数がヌルの場合（デバッグモードのみ）。
   */
  List<String> getAttributes(String key, String attr)
    throws IllegalKeyException;

  /**
   * 指定されたキーに最初に該当する要素を基底要素とする子リソースを取得する。
   * <br>
   * 指定されたキーに該当する要素が存在しない場合は
   * {@link ts.util.resource.Resource#EMPTY}を返す。
   * 引数のキーが不正な場合は例外をスローする。
   *
   * @param  key キー文字列。
   * @return 引数のキーに最初に該当する子リソース。
   * @throws IllegalKeyException キーが不正な場合。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   */
  Resource getFirstChild(String key) throws IllegalKeyException;

  /**
   * 指定されたキーに該当する全ての要素をそれぞれ基底要素とするの子リソースの
   * リストを取得する。
   * <br>
   * 指定されたキーに該当する要素が存在しない場合は空のリストを返す。
   * 引数のキーが不正な場合は例外をスローする。
   *
   * @param  key キー文字列。
   * @return 引数のキーに該当する全要素の子リソースのリスト。
   * @throws IllegalKeyException キーが不正な場合。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   */
  List<Resource> getChildren(String key) throws IllegalKeyException;

  /**
   * 指定されたキーに最初に該当する要素に、値文字列を設定する。
   * <br>
   * 指定されたキーに該当する要素が存在しない場合は、その要素を作成して
   * 値を設定する。
   * 引数のキーが不正な場合は例外をスローする。
   *
   * @param  key キー文字列。
   * @param  value 指定されたキーに最初に該当する要素に設定する値。
   * @throws IllegalKeyException キーが不正な場合。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   */
  void setFirstValue(String key, String value) throws IllegalKeyException;

  /**
   * 指定されたキーに最初に該当する要素を基底要素とする子リソースを取得する。
   * 指定されたキーに該当する要素が存在しない場合は、作成して返す。
   * <br>
   * 引数のキーが不正な場合は例外をスローする。
   *
   * @param  key キー文字列。
   * @return 引数のキーに最初に該当する子リソース。
   * @throws IllegalKeyException キーが不正な場合。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   */
  Resource getOrCreateFirstChild(String key) throws IllegalKeyException;

  /**
   * 指定されたキーに該当する全ての要素を削除する。
   * <br>
   * 指定されたキーに該当する要素が存在しない場合は、そのまま何もしない。
   * 引数のキーが不正な場合は例外をスローする。
   *
   * @param  key キー文字列。
   * @throws IllegalKeyException キーが不正な場合。
   * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
   */
  void removeChildren(String key) throws IllegalKeyException;

  /**
   * 空のリソースオブジェクト。
   */
  static Resource EMPTY = new Resource() {
    /**
     * 基底要素の名前を取得する。
     *
     * @return 基底要素の名前。
     */
    public String getBaseElementName() {
      return "";
    }

    /**
     * 指定されたキーに最初に該当する要素の値文字列を取得する。
     * <br>
     * 常に空文字列を返す。
     *
     * @param  key キー文字列。
     * @return 引数のキーに最初に該当する要素の値文字列。
     * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
     */
    public String getFirstValue(String key)
    {
      assert (key != null) : "@param:key is null.";
      return "";
    }
  
    /**
     * 指定されたキーに該当する全要素の値文字列のリストを取得する。
     * <br>
     * 指定されたキーに該当する要素が存在しない場合は空のリストを返す。
     *
     * @param  key キー文字列。
     * @return 引数のキーに該当する全要素の値文字列のリスト。
     * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
     */
    public List<String> getValues(String key)
    {
      assert (key != null) : "@param:key is null.";
      return new ArrayList<String>(0);
    }

    /**
     * 指定されたキーに最初に該当する要素の、指定された属性の値を取得する。
     * <br>
     * 該当する要素が存在しない場合は空文字列を返す。
     * 該当する要素に、指定された名前の属性が存在しない場合は空文字列を返す。
     * 引数のキーが不正な場合は例外をスローする。
     *
     * @param  key キー文字列。
     * @param  attr 属性名。
     * @return 引数のキーに最初に該当する要素の、指定された属性の値。
     * @throws AssertError 引数がヌルの場合（デバッグモードのみ）。
     */
    public String getFirstAttribute(String key, String attr)
    {
      assert (key != null) : "@param:key is null.";
      assert (attr != null) : "@param:attr is null.";
      return "";
    }
  
    /**
     * 指定されたキーに該当する全要素の、指定された属性の値のリストを取得する。
     * <br>
     * 該当する要素が一つも存在しない場合は空のリストを返す。
     * 引数のキーが不正な場合は例外をスローする。
     *
     * @param  key キー文字列。
     * @param  attr 属性名。
     * @return 引数のキーに該当する全要素の、指定された属性の値のリスト。
     * @throws AssertError 引数がヌルの場合（デバッグモードのみ）。
     */
    public List<String> getAttributes(String key, String attr)
    {
      assert (key != null) : "@param:key is null.";
      assert (attr != null) : "@param:attr is null.";
      return new ArrayList<String>(0);
    }
  
    /**
     * 指定されたキーに最初に該当する要素を基底要素とする子リソースを取得する。
     * <be>
     * 常に{@link ts.util.resource.Resource#EMPTY}を返す。
     *
     * @param  key キー文字列。
     * @return 引数のキーに最初に該当する子リソース。
     * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
     */
    public Resource getFirstChild(String key)
    {
      assert (key != null) : "@param:key is null.";
      return this;
    }
  
    /**
     * 指定されたキーに該当する全ての子リソースのリストを取得する。
     * <br>
     * 常に空のリストを返す。
     *
     * @param  key キー文字列。
     * @return 引数のキーに該当する全要素の子リソースのリスト。
     * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
     */
    public List<Resource> getChildren(String key)
    {
      assert (key != null) : "@param:key is null.";
      return new ArrayList<Resource>(0);
    }
  
    /**
     * 指定されたキーに最初に該当する要素に、値オブジェクトを設定する。
     * <br>
     * このオブジェクトでは常に例外をスローする。
     *
     * @param  key キー。
     * @param  value 指定されたキーに最初に該当する要素に設定する値。
     * @throws UnsupportedOperationException 常にスローされる。
     * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
     */
    public void setFirstValue(String key, String value)
      throws UnsupportedOperationException
    {
      assert (key != null) : "@param:key is null.";
      throw new UnsupportedOperationException();
    }

    /**
     * 指定されたキーに最初に該当する要素を基底要素とする子リソースを取得する。
     * 指定されたキーに該当する要素が存在しない場合は作成して返す。
     * <br>
     * このオブジェクトでは常に例外をスローする。
     *
     * @param  key キー。
     * @return 引数のキーに最初に該当する子リソース。
     * @throws UnsupportedOperationException 常にスローされる。
     * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
     */
    public Resource getOrCreateFirstChild(String key)
      throws UnsupportedOperationException
    {
      assert (key != null) : "@param:key is null.";
      throw new UnsupportedOperationException();
    }

    /**
     * 指定されたキーに該当する全ての要素を削除する。
     * <br>
     * このオブジェクトでは何もしない。
     *
     * @param  key キー文字列。
     * @throws AssertionError 引数がヌルの場合（デバッグモードのみ）。
     */
    public void removeChildren(String key)
    {
      assert (key != null) : "@param:key is null.";
    }
  };
}
