﻿// JavaScript Document

var	jsonlib	= new function(){
	/*文字列のmethod拡張*/
	String.prototype.appTemp	= function(__json){
		/*ローカル関数定義ここから*/
		/*数値の桁取り*/
		var ketatori 				= function(num){
			if(isNaN(num)){
				return num;
			}else{
				var temp = num.toString().split('.');
					temp[0]=temp[0].toString().replace( /([0-9]+?)(?=(?:[0-9]{3})+$)/g , '$1,')
				return temp.join('.');
			}
		}
		/*グローバル変数を展開*/
		var variableConv			= function(__temp,__json){
			var	str	= __temp;
			var	re	= new RegExp('##(.+?)##','ig');
			var	regStr;
			while(regStr=re.exec(__temp)){
				var	_replace_	= RegExp.$1;
				var	_needle		= new RegExp(regStr[0],'g');
				try{
					var	_replace	= eval(_replace_);
				}catch( e ){
					var	_replace	= '';
				}
				str	= str.replace(_needle,_replace)
			}
			return str;
		}
		/*JSON上の変数を展開*/
		var applicationTemplates	= function(__temp,__json,__format){
			var	str	= __temp;
			var	re	= new RegExp(__format,'ig');
			var	regStr;
			while(regStr=re.exec(__temp)){
				/*置換準備*/
				/*_needle	:: 探したい値*/
				/*_replace	:: 置き換える値*/
				var	_replace_	= RegExp.$1;
				var	_needle		= new RegExp(regStr[0].toString().replace(/\[(.+?)\]/,'\\[$1\\]'),'g');
				try{
					var	_replace	= eval('__json.'+_replace_);
				}catch( e ){
					var	_replace	= '';
				}
				if(__format == '@@,(.+?),@@'){
					_replace=ketatori(_replace);
				}
				if(__format == '@@#(.+?)#@@'){
					_replace=(function(){
					   var	temp = _replace.split("\n");
					   return '<p class="kome">※'+temp.join('</p>\n<p class="kome">')+'</p>';
					})();
				}
				/*置換処理*/
				if(_replace===false){
					str	= str.replace(_needle,'');
				}else{
					str	= str.replace(_needle,_replace);
				}
			}
			return str;
		}
		/*条件式に基づいてJSON上の変数を展開*/
		var applicationTemplatesIF_2	= function(__temp,__json){
			var	str	= __temp;
			var	re	= new RegExp('\\[\\[\\[if\\((.+?)\\)\\{(.*?)\\}else\\{(.*?)\\}\\]\\]\\]','ig');
			var	regStr;
			while(regStr=re.exec(__temp)){
				var	_needle	= new RegExp('\\[\\[\\[if\\('+RegExp.$1+'\\)\\{'+RegExp.$2+'\\}else\\{'+RegExp.$3+'\\}\\]\\]\\]','g');
				var _execution_true		= RegExp.$2;
				var _execution_false	= RegExp.$3;
				var	_expression			= RegExp.$1.replace(/this\./ig,"__json.");
				try{
					var	_replace	= (eval('__json.'+_expression))? _execution_true:_execution_false;
				}catch( e ){
					var	_replace	= _execution_false;
				}
				str	= str.replace(_needle,_replace);
			}
			return str;
		}
		/*条件式に基づいてJSON上の変数を展開*/
		var applicationTemplatesIF	= function(__temp,__json){
			var	str	= __temp;
			var	re	= new RegExp('\\[\\[if\\((.+?)\\)\\{(.*?)\\}else\\{(.*?)\\}\\]\\]','ig');
			var	regStr;
			while(regStr=re.exec(__temp)){
				var	_needle	= new RegExp('\\[\\[if\\('+RegExp.$1+'\\)\\{'+RegExp.$2+'\\}else\\{'+RegExp.$3+'\\}\\]\\]','g');
				var _execution_true		= RegExp.$2;
				var _execution_false	= RegExp.$3;
				var	_expression			= RegExp.$1.replace(/this\./ig,"__json.");
				try{
					var	_replace	= (eval('__json.'+_expression))? _execution_true:_execution_false;
				}catch( e ){
					var	_replace	= _execution_false;
				}
				str	= str.replace(_needle,_replace);
			}
			return str;
		}
		/*ローカル関数定義ここまで*/
	
		/*実行部分*/
		var	mySTR	= this;
			mySTR	= variableConv(mySTR,__json);
			mySTR	= applicationTemplatesIF_2(mySTR,__json);
			mySTR	= applicationTemplatesIF(mySTR,__json);
			mySTR	= applicationTemplates(mySTR,__json,'@@\\\/(.+?)\\\/@@');
			mySTR	= applicationTemplates(mySTR,__json,'@@#(.+?)#@@');
			mySTR	= applicationTemplates(mySTR,__json,'@@,(.+?),@@');
		return mySTR.replace(/&lt;(.+?)&gt;/ig,'<$1>');
	};

	this.version	= '1.0.0';
	this.setJSON	= function(json,string,separator){
		var	temp		= new Array();
		var	separator	= (separator)? separator:'\n';
		for(var i in json){
			temp.push(string.appTemp(json[i]));
		}
		return temp.join(separator);
	};
	this.query		= function(queryObj){

		/*オブジェクトのクローンを作成*/
		var cloneObj = function (object){
			var tempObj = new Object();
			for (var _i in object){
				tempObj[_i] = object[_i];
			};
			return tempObj;
		};
	
		/*クエリを分解*/
		var getQUERY	= function(str,separator){
			var	_str		= str.split(separator);
			var	separator	= (separator.match(/like/i))? 'LIKE':separator;
			var	_key		= (_str[0])? _str[0].toString().replace(/^ {0,}(.*?) {0,}$/ig,"$1"):false;
			var	_value		= (_str[1])? (separator=='LIKE')? _str[1].toString().replace(/^ {0,}(.*?) {0,}$/ig,"$1").replace(/%/g,'.*?'):_str[1].toString().replace(/^ {0,}(.*?) {0,}$/ig,"$1"):false;
			return({"key":_key,"value":_value});
		};
	
		/*LIMITクエリ実行部分*/
		var	Q_LIMIT		= function(_obj,LIMIT){
			var	tempObj	= new Array();
			var	n		= new Number();
			var	s		= LIMIT[0];
			var	e		= (LIMIT[1])? LIMIT[1]:false;
			for(var _i in _obj){
				if(e||e===0){
					if((n>=s)&&(e>=n)){
					}else{
						delete _obj[_i];
					}
				}else{
					if(n>=s){
					}else{
						delete _obj[_i];
					}
				}
				n++
			};
			return	_obj;
		};
	
		/*ORDERクエリ実行部分*/
		var	Q_ORDER		= function(_obj,KEY,ORDER){
			if(ORDER){
				var	origin	= new Array();
				var	temp	= new Array();
				var	index	= new Array();
				var	n		= new Number();
				for(var i in _obj){
					temp.push({"index":n,"obj":_obj[i]});
					index[n++]	= i;
				}
				var	path	= '.obj.'+KEY;
				if(ORDER=='DESC'){
					temp.sort (
						function(b1, b2){
							var	_b1	= (isNaN(eval('b1'+path)))? eval('b1'+path):eval('b1'+path)*1;
							var	_b2	= (isNaN(eval('b2'+path)))? eval('b2'+path):eval('b2'+path)*1;
							return _b1 < _b2 ? 1 : -1;
						}
					);
				}else{
					temp.sort (
						function(b1, b2){
							var	_b1	= (isNaN(eval('b1'+path)))? eval('b1'+path):eval('b1'+path)*1;
							var	_b2	= (isNaN(eval('b2'+path)))? eval('b2'+path):eval('b2'+path)*1;
							return _b1 > _b2 ? 1 : -1;
						}
					);
				}
				for(var i in temp){
					if(isNaN(index[temp[i].index]*1)){
						origin[index[temp[i].index]]	= temp[i].obj;
					}else{
						origin.push(temp[i].obj);
					}
				}
				return origin;
			}
		};
	
		/*初期設定*/
		var	myJSON		= (queryObj.JSON)?	queryObj.JSON : new Object();
		var	logic		= (queryObj.LOGIC)?	queryObj.LOGIC : "AND";
		var	query		= (queryObj.QUERY)?	queryObj.QUERY : false;
		var	lock		= (queryObj.LOCK)?	queryObj.LOCK : false;

		var	orLogicJSON	= new Array();
		var	processJSON	= cloneObj(myJSON);
		var	_myLIMIT	= query.split('LIMIT');
		var	_myORDER	= _myLIMIT[0].split("ORDER BY");
		var	_myWHERE	= _myORDER[0].split('WHERE');

		var	myLIMIT 	= (_myLIMIT[1])? _myLIMIT[1].split(","):false;
		var	myORDER		= (_myORDER[1])? _myORDER[1].split(","):false;
		var	myWHERE		= (_myWHERE[1])? _myWHERE[1].split(logic):false;
	
		/*抽出条件適用*/
		if(myWHERE){
			for(var _i=0;myWHERE.length>_i;_i++){
				var	compare		= false;
				var	_query		= myWHERE[_i].toString().replace(/not +?like/i,'NOTLIKE').replace(/^ {0,}(.*?) {0,}$/ig,"$1");
				_query.match(/(.+?) +(.+?) +(.+)/);
				var	target		= RegExp.$1;
				var	separator	= RegExp.$2;
				var	needle		= RegExp.$3.replace(/^ {0,}(.*?) {0,}$/ig,"$1");
	
				switch (separator) {
				case 'like':
				case 'LIKE':
				case 'NOTLIKE':
					var myNeedle	= needle.replace(/%/g,'.*?');
	
					for(var _j in processJSON){
						if(lock){
							var tempJSON	= (isNaN(_j))? eval('processJSON["'+_j+'"].'+lock):eval('processJSON['+_j+'].'+lock);
							if(tempJSON){
								if(logic=='OR'){
									orLogicJSON[_j]	= processJSON[_j];
								}
								continue;
							}
						}
						try{
							var tempJSON	= (isNaN(_j))? eval('processJSON["'+_j+'"].'+target):eval('processJSON['+_j+'].'+target);
							var	re	= new RegExp('^'+myNeedle+'$','ig');
							if(tempJSON.toString().match(re)){
								if(separator=='NOTLIKE'){
									if(logic=='AND'){
										delete processJSON[_j];
									}
								}else{
									if(logic=='OR'){
										orLogicJSON[_j]	= processJSON[_j];
									}
								}
							}else{
								if(separator=='NOTLIKE'){
									if(logic=='OR'){
										orLogicJSON[_j]	= processJSON[_j];
									}
								}else{
									if(logic=='AND'){
										delete processJSON[_j];
									}
								}
							}
						}catch( e ){
							if(logic=='AND'){
								delete processJSON[_j];
							}
						}
					}
					break;
				case '==':
				case '=':
					separator	= '==';
				case '!=':
				case '<=':
				case '<':
				case '>=':
				case '>':
					for(var _j in processJSON){
						if(lock){
							var tempJSON	= (isNaN(_j))? eval('processJSON["'+_j+'"].'+lock):eval('processJSON['+_j+'].'+lock);
							if(tempJSON){
								if(logic=='OR'){
									orLogicJSON[_j]	= processJSON[_j];
								}
								continue;
							}
						}
						try{
							var	tempJSON	= (isNaN(_j))? 			eval('processJSON["'+_j+'"].'+target):eval('processJSON['+_j+'].'+target);
								tempJSON	= (isNaN(tempJSON))?	tempJSON:tempJSON*1;
							var	needle		= (isNaN(needle))?		needle:needle*1;
							if(eval('tempJSON'+separator+'needle')){
								if(logic=='OR'){
									orLogicJSON[_j]	= processJSON[_j];
								}
							}else{
								if(logic=='AND'){
									delete processJSON[_j];
								}
							}
						}catch( e ){
							if(logic=='AND'){
								delete processJSON[_j];
							}
						}
					}
					break;
				case 'between':
				case 'BETWEEN':
					for(var _j in processJSON){
						if(lock){
							var tempJSON	= (isNaN(_j))? eval('processJSON["'+_j+'"].'+lock):eval('processJSON['+_j+'].'+lock);
							if(tempJSON){
								if(logic=='OR'){
									orLogicJSON[_j]	= processJSON[_j];
								}
								continue;
							}
						}
						try{
							var	tempJSON	= (isNaN(_j))? 			eval('processJSON["'+_j+'"].'+target):eval('processJSON['+_j+'].'+target);
								tempJSON	= (isNaN(tempJSON))?	tempJSON:tempJSON*1;
							var	_needle		= needle.toString().split('&');
							var	from		= (isNaN(_needle[0]))?		_needle[0]:_needle[0]*1;
							var	to			= (isNaN(_needle[1]))?		_needle[1]:_needle[1]*1;
							if((tempJSON<=to)&&(tempJSON>=from)){
								if(logic=='OR'){
									orLogicJSON[_j]	= processJSON[_j];
								}
							}else{
								if(logic=='AND'){
									delete processJSON[_j];
								}
							}
						}catch( e ){
							if(logic=='AND'){
								delete processJSON[_j];
							}
						}
					}
					break;
				default:
					break;
				}
			}
		}else{
			orLogicJSON	= cloneObj(myJSON);
		}

		/*OR 条件時の処理*/
		if(logic=='OR'){
			processJSON	= orLogicJSON;
		}

		/*ソート適用*/
		if(myORDER){
			for(var _i=0;myORDER.length>_i;_i++){
				var _ORDER	= myORDER[_i].toString().replace(/ +/ig,' ').replace(/^ {0,}(.*?) {0,}$/ig,"$1").split(' ');
				var	ORDER	= (_ORDER[1])? _ORDER[1]:'ASC';
				processJSON	= Q_ORDER(processJSON,_ORDER[0],ORDER);
			}
		}

		/*出力範囲適用*/
		if(myLIMIT){
			processJSON	= Q_LIMIT(processJSON,myLIMIT);
		}

		return	processJSON;
	};
}

