/*
 * Copyright (c)  2006-2007 Maskat Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * キーと値が対になったプロパティを取得・格納する機能を持ったクラスです。
 * プロパティにはキーごとに型とデフォルト値を定義できます。
 *
 *  - 型が指定された場合、プロパティ値の格納時に自動的に型変換が行われます。
 *  - デフォルト値が指定されている場合、プロパティ値が格納されていなければ
 *    デフォルト値を値として返却します。
 */
maskat.lang.Class.declare("maskat.util.Properties", {

	/**
	 * コンストラクタ
	 *
	 * @param descriptors プロパティ記述子
	 *     {
	 *         プロパティキー: { 
	 *             type: プロパティの型を表す文字列
	 *             defaultValue: デフォルト値
	 *         },
	 *
	 *         プロパティキー: { ... },
	 *         ...
	 *     }
	 */
	initialize: function(descriptors) {
		this.types = {};
		this.defaults = {};
		this.values = {};

		for (var key in descriptors) {
			var desc = descriptors[key];
			this.defineProperty(key, desc.type, desc.defaultValue);
		}
	},

	/**
	 * 新しいプロパティキーを宣言します。
	 *
	 * @param key プロパティキー
	 * @param type プロパティの型を表す文字列
	 *             maskat.util.Converter がサポートする型を指定します。
	 * @param defaultValue デフォルト値
	 */
	defineProperty: function(key, type, defaultValue) {
		this.types[key] = type;
		this.defaults[key] = defaultValue;

		/* プロパティの値がすでに格納されている場合は型を変換 */		
		if (this.values[key]) {
			this.setProperty(key, this.values[key]);
		}
	},

	/**
	 * 指定したキーに対応するプロパティ値を格納します。
	 *
	 * @param key プロパティキー
	 * @param value プロパティの値
	 */
	setProperty: function(key, value) {
		var type = this.types[key];
		if (type) {
			value = maskat.util.Converter.convert(type, value);
		}
		this.values[key] = value;
	},

	/**
	 * プロパティキーと値が対になったオブジェクトから、プロパティ値を
	 * すべて読み込みます。
	 *
	 * @param values プロパティキーと値が対になったオブジェクト 
	 */
	setProperties: function(values) {
		for (var key in values) {
			this.setProperty(key, values[key]);
		}
	},

	/**
	 * 指定された URL から HTTP GET メソッドで JSON 形式のリテラル文字列を
	 * 取得し、そこからプロパティキーと値を読み込みます。
	 *
	 * @param url JSON ファイルを取得する URL
	 */
	load: function(url) {
		this.setProperties(maskat.util.CrossBrowser.loadJSONFrom(url));
	},

	/**
	 * 指定したキーに対応するプロパティ値を返します。
	 *
	 * @return 指定したキーに対応するプロパティ値 
	 */
	getProperty: function(key) {
		return this.values[key] || this.defaults[key];
	},

	/**
	 * すべてのプロパティキーと値が対になったオブジェクトを返します。
	 *
	 * @return プロパティキーと値が対になったオブジェクト 
	 */
	getProperties: function() {
		var result = {};
		var key;

		/* デフォルト値を result オブジェクトに格納 */
		for (key in this.defaults) {
			result[key] = this.defaults[key];
		} 

		/* プロパティ値を result オブジェクトに格納 */
		for (key in this.values) {
			result[key] = this.values[key];
		} 

		return result;
	}

});
