/********************************************************************************
 COPYRIGHT(C):  IAAA-2003
 PROYECTO:      Búsquedas
 ARCHIVO:       FilterBuilderToolkitObject.js
 CREACION:      26-02-04 esoroa
 ULTIMA MODIF:
 LENGUAJE:      Javascript
 PLATAFORMA:    Windows 95-NT, debe funcionar en todas
 REQUERIM.:
 DESCRIPCION:   Herramientas de utilería para la construcción y manejo de
                consultas a catálogo con filter encoding.
 HISTORIA:      26-02-04 esoroa Creación
*******************************************************************************/


function FilterBuilderToolkitObject(){
	// Cabeceras de queryTrees.
	this.FILTER_HEAD = "<Filter>";
	this.FILTER_FOOT = "</Filter>";

	this.LITERAL_HEAD = "<Literal>";
	this.LITERAL_FOOT = "</Literal>";

	this.PROPERTY_NAME_HEAD = "<PropertyName>";
	this.PROPERTY_NAME_FOOT = "</PropertyName>";


	// BBOX
	this.BBOX_HEAD = "<BBOX>";
	this.BBOX_FOOT = "</BBOX>";
	this.BOX_HEAD =  "<Box>";
	this.EXTENT_BOX_HEAD_I =  "<Box srsName=\"http://www.opengis.net/gml/srs/epsg.xml#";
	this.EXTENT_BOX_HEAD_II =  "\">";
	this.BOX_FOOT =  "</Box>";
	this.COORDINATES_HEAD = "<coordinates>";
	this.COORDINATES_FOOT = "</coordinates>";


	// operadores lógicos de unión
	this.AND_OP = "AND";
	this.AND_HEAD = "<And>";
	this.AND_FOOT = "</And>";

	this.OR_OP = "OR";
	this.OR_HEAD = "<Or>";
	this.OR_FOOT = "</Or>";

	this.NOT_OP = "NOT";
	this.NOT_HEAD = "<Not>";
	this.NOT_FOOT = "</Not>";

	// operaciones
	this.EQUALS_OP = "=";
	this.EQUALS_FILTER_HEAD_CHAIN = "<PropertyIsEqualTo>";
	this.EQUALS_FILTER_FOOT_CHAIN = "</PropertyIsEqualTo>";

	this.CONTAINS_OP = "CONTAINS WORD";
	this.CONTAINS_FILTER_HEAD_CHAIN = "<PropertyIsLike>";
	this.CONTAINS_FILTER_FOOT_CHAIN = "</PropertyIsLike>";

	this.LESS_EQUAL_OP = "<=";
	this.LESSEQUAL_FILTER_HEAD_CHAIN = "<PropertyIsLessThanOrEqualTo>";
	this.LESSEQUAL_FILTER_FOOT_CHAIN = "</PropertyIsLessThanOrEqualTo>";

	this.GREAT_EQUAL_OP = ">=";
	this.GREATEQUAL_FILTER_HEAD_CHAIN = "<PropertyIsGreaterThanOrEqualTo>";
	this.GREATEQUAL_FILTER_FOOT_CHAIN = "</PropertyIsGreaterThanOrEqualTo>";

	this.LESS_OP = "<";
	this.LESS_FILTER_HEAD_CHAIN = "<PropertyIsLessThan>";
	this.LESS_FILTER_FOOT_CHAIN = "</PropertyIsLessThan>";

	this.GREAT_OP = ">";
	this.GREAT_FILTER_HEAD_CHAIN = "<PropertyIsGreaterThan>";
	this.GREAT_FILTER_FOOT_CHAIN = "</PropertyIsGreaterThan>";


	// Atributos para construir las preguntas.
	this.SPATIAL_SEARCH_ATTRIBUTE = "Geometry"; //"GeographicalCoordinates";
	this.SPATIAL_SEARCH_N_POINTS = 2;

	// Atributos para construir las preguntas.
	this.THEME_SEARCH_ATTRIBUTE = "subject";
	this.TEMPORAL_SEARCH_ATTRIBUTE = "date";
	this.SCALE_SEARCH_ATTRIBUTE = "scale";
	this.LOCATION_SEARCH_ATTRIBUTE = "spatial";
	this.PUBLISHER_SEARCH_ATTRIBUTE = "publisher";
	this.LANGUAGE_SEARCH_ATTRIBUTE = "language";


}

function isArray(obj) {
   if (obj.constructor.toString().indexOf("Array") == -1)
      return false;
   else
      return true;
}


/*  Unifica dos queryTrees sin cabecera para formar uno nuevo utilizo el
 * operador lógico pasado como argumento.
 */
FilterBuilderToolkitObject.prototype.logicalBinaryUnification = function(firstFilter, secondFilter, logicalOperator)
{
   var filterUnified = null;

  switch(logicalOperator.toUpperCase())
  {
  	case this.AND_OP:
	                   filterUnified= this.AND_HEAD + firstFilter + secondFilter + this.AND_FOOT;
  		break;
  	case this.OR_OP:
  	                   filterUnified= this.OR_HEAD + firstFilter + secondFilter + this.OR_FOOT;
  		break;
  	default:
  		alert("FilterBuilderToolkitObject: operación lógica inválida "+logicalOperator);
  }


   return filterUnified;
}

FilterBuilderToolkitObject.prototype.logicalNegation = function(filter)
{
	var negFilter = this.NOT_HEAD + filter + this.NOT_FOOT;
	return negFilter;
}

FilterBuilderToolkitObject.prototype.logicalMultipleUnification = function(queryTreeArray, logicalOperator)
{
   var listSize = -1;
   var operatorSize = -1;
   var unifiedQueryTree = null;
   var queryTree1 = null;
   var queryTree2 = null;
   var queryTree3 = null;
   var queryTreeArrayAux = new Array();

   queryTreeArrayPrima = queryTreeArray;

   listSize = queryTreeArray.length;


   if (isArray(logicalOperator))
   {
          operatorSize = logicalOperator.length;
          while (logicalOperator.length > 0)
          {
	     queryTree1 = queryTreeArray[0];
             queryTreeArray = shiftArray(queryTreeArray);
             queryTree2 = queryTreeArray[0];

             queryTree3 = this.logicalBinaryUnification(queryTree1, queryTree2, logicalOperator[0]);
             queryTreeArray[0] = queryTree3;
             logicalOperator = shiftArray(logicalOperator);
          }
          unifiedQueryTree = queryTreeArray[0];
   }
   else
   {
      while (queryTreeArray.length > 1)
      {
         queryTree1 = queryTreeArray[0];
         queryTreeArray = shiftArray(queryTreeArray);
	 queryTree2 = queryTreeArray[0];

	 unifiedQueryTree = this.logicalBinaryUnification(queryTree1, queryTree2, logicalOperator);
         queryTreeArray[0] = unifiedQueryTree;
      }
      unifiedQueryTree = queryTreeArray[0];
   }

   return unifiedQueryTree;
}



/*  Shift array elements down.
 */
function shiftArray(array)
{
   var newArray = new Array();
   var arrayLength = array.length;

   if (arrayLength < 2)
   {
      return newArray;
   }
   for (i = 1; i < arrayLength; i++)
   {
      newArray[i-1] = array[i];
   }
   return newArray;
}


/* Añade la cabecera y pie del filter
 */
FilterBuilderToolkitObject.prototype.wrapIntoXmlHeader = function(filter)
{
   var filterXml = null;

   filterXml = this.FILTER_HEAD + filter + this.FILTER_FOOT;

   return filterXml;
}



/*  Crea un queryTree con el atributo, valor y operador especificados.
 */
FilterBuilderToolkitObject.prototype.createFilterRestriction = function(attribute, value, operator)
{

  // HABRÁ QUE HACER UN CASE CON LOS QUERYOPERATOR.
   var filter = null;

  switch(operator)
  {
  	case this.EQUALS_OP:
		filter = this.EQUALS_FILTER_HEAD_CHAIN;
		filter = filter + this.PROPERTY_NAME_HEAD + attribute + this.PROPERTY_NAME_FOOT;
		filter = filter + this.LITERAL_HEAD + value + this.LITERAL_FOOT;
		filter = filter + this.EQUALS_FILTER_FOOT_CHAIN;
  		break;
  	case this.CONTAINS_OP:
		filter = this.CONTAINS_FILTER_HEAD_CHAIN;
		filter = filter + this.PROPERTY_NAME_HEAD + attribute +this.PROPERTY_NAME_FOOT;
		filter = filter + this.LITERAL_HEAD + value + this.LITERAL_FOOT;
		filter = filter + this.CONTAINS_FILTER_FOOT_CHAIN;
  		break;
    	case this.GREAT_EQUAL_OP:
		filter = this.GREATEQUAL_FILTER_HEAD_CHAIN;
		filter = filter + this.PROPERTY_NAME_HEAD + attribute +this.PROPERTY_NAME_FOOT;
		filter = filter + this.LITERAL_HEAD + value + this.LITERAL_FOOT;
		filter = filter + this.GREATEQUAL_FILTER_FOOT_CHAIN;
  		break;
    	case this.LESS_EQUAL_OP:
		filter = this.LESSEQUAL_FILTER_HEAD_CHAIN;
		filter = filter + this.PROPERTY_NAME_HEAD + attribute +this.PROPERTY_NAME_FOOT;
		filter = filter + this.LITERAL_HEAD + value + this.LITERAL_FOOT;
		filter = filter + this.LESSEQUAL_FILTER_FOOT_CHAIN;
  		break;
    	case this.GREAT_OP:
		filter = this.GREAT_FILTER_HEAD_CHAIN;
		filter = filter + this.PROPERTY_NAME_HEAD + attribute +this.PROPERTY_NAME_FOOT;
		filter = filter + this.LITERAL_HEAD + value + this.LITERAL_FOOT;
		filter = filter + this.GREAT_FILTER_FOOT_CHAIN;
  		break;
    	case this.LESS_OP:
		filter = this.LESS_FILTER_HEAD_CHAIN;
		filter = filter + this.PROPERTY_NAME_HEAD + attribute +this.PROPERTY_NAME_FOOT;
		filter = filter + this.LITERAL_HEAD + value + this.LITERAL_FOOT;
		filter = filter + this.LESS_FILTER_FOOT_CHAIN;
  		break;
  	default:
  		alert("FilterBuilderToolkitObject: operación inválida");
  }

   return filter;
}


FilterBuilderToolkitObject.prototype.createFilterByGeomCoordinates = function (north, south, east, west, referenceSystem)
{
   var filter = null;

   filter = this.BBOX_HEAD;
   filter = filter + this.PROPERTY_NAME_HEAD  + this.SPATIAL_SEARCH_ATTRIBUTE + this.PROPERTY_NAME_FOOT;
   if (referenceSystem != undefined)
   {
        filter = filter + this.EXTENT_BOX_HEAD_I + referenceSystem + this.EXTENT_BOX_HEAD_II;
   }
   else
   {
        filter = filter + this.BOX_HEAD;
   }

   filter = filter + this.COORDINATES_HEAD + west + ',' + south +  ' ' + east + ',' + north + this.COORDINATES_FOOT;

   filter = filter + this.BOX_FOOT;
   filter = filter + this.BBOX_FOOT;

   return filter;
}



/*  Crea un queryTree para preguntar por el tema que se especifica como argumento.
 */
FilterBuilderToolkitObject.prototype.createFilterByTheme = function(themeValue, queryOperator)
{
   var filter = null;

   filter = this.createFilterRestriction(this.THEME_SEARCH_ATTRIBUTE, themeValue, queryOperator);

   return filter;
}


/*  Crea un queryTree para preguntar por el lenguaje que se especifica como argumento.
 */
FilterBuilderToolkitObject.prototype.createFilterByLanguage = function(languageValue, queryOperator)
{
   var filter = null;

   filter = this.createFilterRestriction(this.LANGUAGE_SEARCH_ATTRIBUTE, languageValue, queryOperator);

   return filter;
}


/*  Crea un queryTree para preguntar por la fuente que se especifica como argumento.
 */
FilterBuilderToolkitObject.prototype.createFilterByPublisher = function(publisherValue, queryOperator)
{
   var filter = null;

   filter = this.createFilterRestriction(this.PUBLISHER_SEARCH_ATTRIBUTE, publisherValue, queryOperator);

   return filter;
}


FilterBuilderToolkitObject.prototype.createFilterByDate = function(dateValue, queryOperator)
{
   var filter = null;

   filter = this.createFilterRestriction(this.TEMPORAL_SEARCH_ATTRIBUTE, dateValue, queryOperator);

   return filter;
}


FilterBuilderToolkitObject.prototype.createFilterByScale = function(scaleValue, queryOperator)
{
   var filter = null;

   filter = this.createFilterRestriction(this.SCALE_SEARCH_ATTRIBUTE, scaleValue, queryOperator);

   return filter;
}


FilterBuilderToolkitObject.prototype.createFilterByLocation = function(locationValue, queryOperator)
{
   var filter = null;

   filter = this.createFilterRestriction(this.LOCATION_SEARCH_ATTRIBUTE, locationValue, queryOperator);

   return filter;
}


