package se.timeoff;

//
//  TODisplayGroup.java
//  knacdamage
//
//  Created by Fredrik Lindgren on 2007-10-13.
//  Copyright (c) 2007 drop. All rights reserved.
//

import com.webobjects.appserver.WODisplayGroup;
import com.webobjects.eocontrol.EOAndQualifier;
import com.webobjects.eocontrol.EOKeyValueQualifier;
import com.webobjects.eocontrol.EONotQualifier;
import com.webobjects.eocontrol.EOQualifier;
import com.webobjects.eocontrol._EOFlatMutableDictionary;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSMutableArray;
import com.webobjects.foundation.NSMutableDictionary;

/** Extends the WODisplayGroup with an array for all qualified objects. 
 * The WODisplayGroup looses this functionality when we set a batch size.<br/><br/>
 * 
 * There is also a queryMatchAll dictionary that can be used on text field searches with 
 * for example "fault, error, -letter" which creates a qualifier that finds records with 
 * the text string "fault" and "error" and excludes "letter".
 * It also has support for operators like '<' and' >'.
 * 
 * @author Fredrik Lindgren drop&search systems AB
 */
public class TODisplayGroup extends WODisplayGroup {
	private NSArray<EOQualifier> addedQualifiers;
	// _EOFlatMutableDictionary is used by the WODisplayGroup for the other queryDictionaries
	// to prevent keyValue coding to evaluate after the dictionary.
	private _EOFlatMutableDictionary _queryMatchAll = new _EOFlatMutableDictionary();
		
	/** An array with all objects qualified with the qualifier set by the display group. */
	public NSArray qualifiedObjects() {
		int numberOfObjectsPerBatch = numberOfObjectsPerBatch();
		int currentBatchIndex = currentBatchIndex();
		setNumberOfObjectsPerBatch(0);
		NSArray qualifiedObjects = displayedObjects();
		setNumberOfObjectsPerBatch(numberOfObjectsPerBatch);
		setCurrentBatchIndex(currentBatchIndex);
		return qualifiedObjects;
	}
	
	/**
	 * The <CODE>qualifierFromQueryValues</CODE> method uses this dictionary along with the <CODE>queryMatchAll</CODE> 
	 * and <CODE>queryMin</CODE> dictionaries to construct qualifiers.
 	 * <P>
 	 * Use the <CODE>queryOperator</CODE> dictionary to specify the type of matching (=, &lt;, &gt;, <b>like</b>, and so on) 
 	 * for each key in the <CODE>queryMatch</CODE> dictionary.
 	 * <P>
 	 * If the <CODE>queryOperator</CODE> dictionary does not contain a key contained in 
 	 * the <CODE>queryMatch</CODE> dictionary, the default is to match the value exactly (=) 
 	 * if the value is a number or a date and to perform pattern matching if the value is a String. 
 	 * In the case of string values, the <CODE>defaultStringMatchFormat</CODE> and <CODE>defaultStringMatchOperator</CODE> 
 	 * specify exactly how the pattern matching will be performed.
 	 * 
 	 * @return a dictionary of query values to match
 	 * 
 	 * @see #allQualifierOperators()
 	 * @see #defaultStringMatchFormat()
 	 * @see #defaultStringMatchOperator()
 	 * @see #qualifierFromQueryValues()
 	 * @see #qualifyDataSource()
 	 * @see #qualifyDisplayGroup()
 	 * @see #queryMatch()
 	 * @see #queryMax()
 	 * @see #queryMin()
 	 * @see #queryOperator()
 	 * @see #relationalQualifierOperators()
 	 * 
 	 * @author fredrik
	*/
 	public NSMutableDictionary<String, String> queryMatchAll() {
		return _queryMatchAll;
	}
	
	private NSArray<? extends EOQualifier> queryMatchAllQualifiers() {
		NSMutableArray<EOQualifier> quals = new NSMutableArray<EOQualifier>();

		for (String key:queryMatchAll().allKeys()) {
			quals.addAll(qualifersFromKeyAndTokens(key, queryMatchAll().get(key)));
		}
		return quals;
	}
	
	private NSArray<? extends EOQualifier> qualifersFromKeyAndTokens(String key, String tokens) {
		NSMutableArray<EOQualifier> keyQualifiers = new NSMutableArray<EOQualifier>();
		EOQualifier subQualifier;
		for (String token:tokens.trim().split("[\\s,]+")) {
			char operator = token.charAt(0);
			switch (operator) {
			case '-':
				token = token.substring(1);
				subQualifier = new EONotQualifier(new EOKeyValueQualifier(key, EOQualifier.QualifierOperatorCaseInsensitiveLike, "*" + token + "*")); 
				break;
			case '<':
				token = token.substring(1);
				subQualifier = new EOKeyValueQualifier(key, EOQualifier.QualifierOperatorLessThan, token); 
				break;
			case '>':
				token = token.substring(1);
				subQualifier = new EOKeyValueQualifier(key, EOQualifier.QualifierOperatorGreaterThan, token); 
				break;
			default:
				subQualifier = new EOKeyValueQualifier(key, EOQualifier.QualifierOperatorCaseInsensitiveLike, "*" + token + "*"); 
				break;
			}
			keyQualifiers.add(subQualifier);
		}
		return keyQualifiers;
	}

	public EOQualifier qualifierFromQueryValues() {
		NSMutableArray<EOQualifier> combinedQualifiers = new NSMutableArray<EOQualifier>();
		
		EOQualifier qualifierFromQueryValues = super.qualifierFromQueryValues();
				
		if (qualifierFromQueryValues != null)
			combinedQualifiers.add(qualifierFromQueryValues);
		
		if (addedQualifiers != null)
			combinedQualifiers.addAll(addedQualifiers);
		
		combinedQualifiers.addAll(queryMatchAllQualifiers());
		
		if (combinedQualifiers.count() > 0)
			return new EOAndQualifier(combinedQualifiers);
		
		return qualifierFromQueryValues;
	}

	/**
	 * @return the addedQuery
	 */
	public NSArray<EOQualifier> addedQualifiers() {
		return addedQualifiers;
	}

	/**
	 * @param addedQuery the addedQuery to set
	 */
	public void setAddedQualifiers(NSArray<EOQualifier> addedQualifiers) {
		this.addedQualifiers = addedQualifiers;
	}
	

}
