/*
 * $Id: SearchDocumentsForm.java,v 1.39 2006/10/30 12:29:56 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: SearchDocumentsForm.java,v $
 * Revision 1.39  2006/10/30 12:29:56  marbobo
 * + Überprüfung der Syntax für Suchanfragen (Jetzt auch für die Schnellsuche)
 *
 * Revision 1.38  2006/10/30 11:55:28  marbobo
 * + Überprüfung der Syntax für Suchanfragen
 *
 * Revision 1.37  2006/07/13 23:15:44  marbobo
 * + TDF-Format aus der Auswahlbox entfernt
 * + Dokumentformate sortiert
 *
 * Revision 1.36  2006/05/27 18:34:47  marbobo
 * + Neueste Lucene-Version eingebaut
 *
 * Revision 1.35  2006/03/15 12:39:24  marbobo
 * + Refactoring
 *
 * Revision 1.34  2005/09/04 23:36:00  marbobo
 * + Bugfix (Suchanfrage)
 *
 * Revision 1.33  2005/09/04 23:21:22  marbobo
 * +Suche nach Metadaten-Attribute (Erstellungsdatum) für Dokumente implementiert
 *
 * Revision 1.32  2005/08/14 18:13:59  marbobo
 * + Alternative-Sicht implementiert
 *
 * Revision 1.31  2005/05/02 15:24:51  marbobo
 * +Ergänzungen und Bugfixing bzgl. der Speicherung der Sortierungeinstellungen in der Session
 *
 * Revision 1.30  2005/04/29 10:50:55  korowa
 * Die gespeicherte im Datenbank Sortierungsarten werden jetzt am Anfang jeder Sitzung
 * geladen und aktiviert.
 *
 * Revision 1.29  2005/04/22 07:39:06  korowa
 * Die Sortierungsart von Search bleibt über die ganze Sitzung erhalten
 *
 * Revision 1.28  2004/11/09 20:14:58  marbobo
 * + Suche nach Herausgeber
 *
 * Revision 1.27  2004/10/06 12:33:38  marbobo
 * + Suche nach Globalen Dokument-Attributen korrigiert
 *
 * Revision 1.26  2004/10/05 17:59:50  marbobo
 * + Suche nach Globalen Dokument-Attributen überarbeitet
 *
 * Revision 1.25  2004/09/15 14:18:56  marbobo
 * + Volltextsuche korrigiert
 * + Suche über alle Felder
 *
 * Revision 1.24  2004/09/04 14:41:18  marbobo
 * + kleine Anpassung
 *
 * Revision 1.23  2004/09/03 00:42:43  marbobo
 * + Kategorieauswahl über ein Explorer für die Suche eingebaut
 *
 * Revision 1.22  2004/08/25 17:59:05  marbobo
 * + Bugfix ( Benutzerquery erstellen )
 *
 * Revision 1.21  2004/06/27 17:26:50  marbobo
 * + Quellcode maintenance
 *
 * Revision 1.20  2004/04/27 11:37:54  marbobo
 * + Suche nach "Dateinamen" hinzugefügt
 *
 * Revision 1.19  2004/04/26 21:59:26  marbobo
 * + Dokumentsicht erweitert (mit/ohne Details)
 *
 * Revision 1.18  2004/04/17 21:00:46  marbobo
 * + Suche im beliebigem Zeitraum
 *
 * Revision 1.17  2004/03/25 14:39:05  marbobo
 * Handling der Ergebnisseiten angepasst
 *
 * Revision 1.16  2004/03/25 01:52:47  marbobo
 * Suche nach Bestimmten Dokumenttypen gefixt (nochmal)
 *
 * Revision 1.15  2004/03/24 19:07:15  marbobo
 * Suche nach Bestimmten Dokumenttypen gefixt
 *
 * Revision 1.14  2004/03/23 19:47:54  marbobo
 * SearchDocumentsAction und SearchDocumentsForm neu überarbeitet
 * und auf Request-Scope umgestellt
 *
 */
package vkc.search.form;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Vector;

import javax.servlet.http.HttpServletRequest;

import org.apache.lucene.document.DateTools;
import org.apache.lucene.document.DateTools.Resolution;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionMapping;

import vkc.db.entities.VKCAddAttribute;
import vkc.db.entities.VKCCategory;
import vkc.db.entities.VKCDocumentType;
import vkc.db.serializer.VKCAddAttributeSerializer;
import vkc.db.serializer.VKCCategorySerializer;
import vkc.db.serializer.VKCDocumentClassSerializer;
import vkc.db.serializer.VKCDocumentStatusSerializer;
import vkc.db.serializer.VKCDocumentTypeSerializer;
import vkc.exception.DBException;
import vkc.search.Search;
import vkc.util.DateUtils;
import vkc.util.StringUtils;
import vkc.util.VKCCategoryAbsPath;
import vkc.util.VKCStringUtils;
import vkc.util.sort.DocumentTypeSortFactory;
import vkc.view.form.DynaForm;


/**
 * Form Bean für die Darstellung von Suchergebnissen
 *
 * @author marbobo
 * @version $Revision: 1.39 $
 */
public final class SearchDocumentsForm extends DynaForm {
    //~ Instance fields --------------------------------------------------------
    private String  	searchInAnyField				= "";
	private String  	searchInFullText				= "";
	private String  	searchForCreationDateFrom		= "";
	private String  	searchForCreationDateUntil		= "";
	private String  	searchForDynaAttributeNames		= "";
	private String  	searchForDynaAttributeValues	= "";
	private String  	searchForFilename				= "";
    private String  	searchForTitle					= "";
    private String  	searchForKeywords				= "";
    private String  	searchForDescription			= "";
    private String  	searchForAuthor					= "";
    private String  	searchForPublisher				= "";
    private String		selectedSortResults				= "1";
    private String  	selectedNumberOfResultsPerPage	= "5";
    private String  	selectedSearchResultLimitation	= "*";
	private String  	selectedCategoryId				= String.valueOf(VKCCategory.ROOT_CATEGORY_ID);
    private String  	searchFromHereText				= "";
	private String  	selectedDocClassId				= "-1";
	private String  	selectedDocStatusId				= "-1";
	private String  	validFrom						= "";
	private String  	validUntil						= "";
    private Integer 	currentResultPageId				= new Integer(1);
	private Integer 	hitsCount						= new Integer(0);
	private Integer 	pageCount						= new Integer(1);
	private Integer 	startIndex						= new Integer(0);
    private Double  	searchTime						= new Double(0);
	private boolean 	hitsFound						= false;
	private boolean 	searching						= false;
    private HashMap 	addDocAttributes				= new HashMap();
	private HashMap		allAddDocAttributes				= null;
    private List		results							= new ArrayList(); 
	private Integer 	selectedId 						= null;
	private Integer[] 	showDocumentDetails 			= new Integer[0];
	private Integer[] 	showDocuments 					= new Integer[0];

    //~ Methods ----------------------------------------------------------------

	/**
	 * Reset der Eingabefelder auf Defaultwerte
	 *
	 * @param mapping The mapping used to select this instance
	 * @param request The servlet request we are processing
	 */
	public void reset(ActionMapping mapping, HttpServletRequest request) {
		super.reset(mapping, request);
		
		searchInAnyField				= "";
		searchInFullText				= "";
		searchForCreationDateFrom		= "";
		searchForCreationDateUntil		= "";
		searchForDynaAttributeNames		= "";
		searchForDynaAttributeValues	= "";
		searchForFilename				= "";
		searchForTitle					= "";
		searchForKeywords				= "";
		searchForDescription			= "";
		searchForAuthor					= "";
	    searchForPublisher				= "";
		selectedNumberOfResultsPerPage	= "5";
		selectedSearchResultLimitation	= "*";
		selectedCategoryId				= String.valueOf(VKCCategory.ROOT_CATEGORY_ID);
		searchFromHereText				= "";
		selectedDocClassId				= "-1";
		selectedDocStatusId				= "-1";
		validFrom						= "";
		validUntil						= "";
		currentResultPageId				= new Integer(1);
		hitsCount						= new Integer(0);
		pageCount						= new Integer(1);
		startIndex						= new Integer(0);
		searchTime						= new Double(0);
		hitsFound						= false;
		searching						= false;
		addDocAttributes				= new HashMap();
		allAddDocAttributes				= null;
		results							= new ArrayList(); 
		selectedId 						= null;
		showDocumentDetails 			= new Integer[0];
		showDocuments 					= new Integer[0];
		
		//Nachsehen ob in der Session Einstellungen für die Sortierung existiert
		if (request.getSession().getAttribute("searchDocumentSortMode") == null) {
			//Wenn nicht werden die Einstellungen aus dem User-Objekt geholt
        	if (getUser() != null && getUser().getSearchDocumentSortMode() != null) {
            	request.getSession().setAttribute("searchDocumentSortMode", getUser().getSearchDocumentSortMode());
        	    selectedSortResults = getUser().getSearchDocumentSortMode().toString();
        	} else {
            	selectedSortResults = "1";
        	}
		} else {
        	selectedSortResults = ((Integer)request.getSession().getAttribute("searchDocumentSortMode")).toString();
		}
	}

	/**
	 * Validiert die Eingabefelder und gibt gegebenfalls die Fehler zurück
	 *
	 * @param mapping The mapping used to select this instance
	 * @param request The servlet request we are processing
	 */
	public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
		ActionErrors errors = new ActionErrors();
		
		if (isSearchAction(request)) {		
			String from  = getSearchForCreationDateFrom();
			String until = getSearchForCreationDateUntil();
			Date f = null;
			Date u = null;
				
			if (!isEmpty(from)) {
				if ((f = DateUtils.parseDate(from)) == null) {
					errors.add("creationDateFrom", new ActionError("error.creation.date"));
				}
			}

			if (!isEmpty(until)) {
				if ((u = DateUtils.parseDate(until)) == null) {
					errors.add("creationDateUntil", new ActionError("error.creation.date"));
				}
			}
				
			if (f != null && u != null && f.after(u)) {
				errors.add("creationDate", new ActionError("error.date.range"));
			}

			from  = getValidFrom();
			until = getValidUntil();
			f = null;
			u = null;
				
			if (!isEmpty(from)) {
				if ((f = DateUtils.parseDate(from)) == null) {
					errors.add("validFrom", new ActionError("error.date"));
				}
			}

			if (!isEmpty(until)) {
				if ((u = DateUtils.parseDate(until)) == null) {
					errors.add("validUntil", new ActionError("error.date"));
				}
			}
				
			if (f != null && u != null && f.after(u)) {
				errors.add("date", new ActionError("error.date.range"));
			}
			
			if (isQuickSearchAction(request)) {
				setSearchInAnyField(VKCStringUtils.base64Decode(getSearchFromHereText()));
				
				if (!Search.parseSearchQuerySyntax(getSearchInAnyField())) {
					errors.add("searchQuerySyntax", new ActionError("error.query.syntax"));
				}
			} else {
				if (!Search.parseSearchQuerySyntax(getSearchQuery())) {
					errors.add("searchQuerySyntax", new ActionError("error.query.syntax"));
				}
			}
		}

		return errors;
	}

    public void setSearchInAnyField(String s) {
        searchInAnyField = StringUtils.normalize(s);
    }

    public String getSearchInAnyField() {
        return searchInAnyField;
    }

    public void setSearchInFullText(String s) {
        searchInFullText = StringUtils.normalize(s);
    }

    public String getSearchInFullText() {
        return searchInFullText;
    }

	public void setSearchForDynaAttributeNames(String s) {
		searchForDynaAttributeNames = StringUtils.normalize(s);
	}

	public String getSearchForDynaAttributeNames() {
		return searchForDynaAttributeNames;
	}

	public void setSearchForDynaAttributeValues(String s) {
		searchForDynaAttributeValues = StringUtils.normalize(s);
	}

	public String getSearchForDynaAttributeValues() {
		return searchForDynaAttributeValues;
	}

    public void setSearchForTitle(String s) {
        searchForTitle = StringUtils.normalize(s);
    }

    public String getSearchForTitle() {
        return searchForTitle;
    }

    public void setSearchForKeywords(String s) {
        searchForKeywords = StringUtils.normalize(s);
    }

    public String getSearchForKeywords() {
        return searchForKeywords;
    }

	public void setSearchForFilename(String s) {
		searchForFilename = StringUtils.normalize(s);
	}

	public String getSearchForFilename() {
		return searchForFilename;
	}

    public void setSearchForDescription(String s) {
        searchForDescription = StringUtils.normalize(s);
    }

    public String getSearchForDescription() {
        return searchForDescription;
    }

    public void setSearchForAuthor(String s) {
        searchForAuthor = StringUtils.normalize(s);
    }

    public String getSearchForAuthor() {
        return searchForAuthor;
    }

    public void setSearchForPublisher(String s) {
        searchForPublisher = StringUtils.normalize(s);
    }

    public String getSearchForPublisher() {
        return searchForPublisher;
    }

    public void setSelectedSortResults(String s) {
        selectedSortResults = StringUtils.normalize(s);
        
    }

    public String getSelectedSortResults() {
        return selectedSortResults;
        
    }

    public void setSelectedNumberOfResultsPerPage(String s) {
        selectedNumberOfResultsPerPage = StringUtils.normalize(s);
    }

    public String getSelectedNumberOfResultsPerPage() {
        return selectedNumberOfResultsPerPage;
    }

    public void setSelectedSearchResultLimitation(String s) {
        selectedSearchResultLimitation = StringUtils.normalize(s);
    }

    public String getSelectedSearchResultLimitation() {
        return selectedSearchResultLimitation;
    }

    public void setSearchFromHereText(String s) {
        searchFromHereText = StringUtils.normalize(s);
    }

    public String getSearchFromHereText() {
        return searchFromHereText;
    }

    public void setSearchTime(Double d) {
        searchTime = d;
    }

    public Double getSearchTime() {
        return searchTime;
    }

    public void setCurrentResultPageId(Integer id) {
        currentResultPageId = id;
    }

    public Integer getCurrentResultPageId() {
        return currentResultPageId;
    }

	public Integer getNextPageId() {
		return new Integer(getCurrentResultPageId().intValue() + 1);
	}

	public Integer getPreviousPageId() {
		return new Integer(getCurrentResultPageId().intValue() - 1);
	}

	public HashMap getAllAddDocAttributes() throws DBException {
		if (allAddDocAttributes == null) {
			allAddDocAttributes = new HashMap();
		    Vector addDocAttr = VKCAddAttributeSerializer.getAllAddDocAttributes();
	        
			for (int i = 0; i < addDocAttr.size(); i++) {
				VKCAddAttribute addAttribute = (VKCAddAttribute)addDocAttr.get(i);
				allAddDocAttributes.put("adddocattrId_" + addAttribute.getAttrId(), addAttribute);
			}
		}
		
	    return allAddDocAttributes;
	}

	public HashMap getAddDocAttributes() {
		return addDocAttributes;
	}

	public void setAddDocAttributes(HashMap m) {
		addDocAttributes = m;
	}

	public Object getAddDocAttrValue(String key) {
		return addDocAttributes.get(key);
	}

	public void setAddDocAttrValue(String key, Object value) {		
		addDocAttributes.put(key, StringUtils.normalize((String)value));
	}

	public boolean isSearchedForAddDocAttributes() {
		if (addDocAttributes.isEmpty()) {
			return false;
		}

		Iterator itKeys = addDocAttributes.keySet().iterator();
		
		while (itKeys.hasNext()) {
			String fieldName = (String)itKeys.next();
			String fieldValue = (String)addDocAttributes.get(fieldName);

			if (!"".equals(fieldValue)) {
				return true;
			}
		}
		
		return false;
	}
	
	public boolean isSearchedDocClasses() {
		return !"-1".equalsIgnoreCase(getSelectedDocClassId());
	}
	
	public boolean isSearchedDocStatus() {
		return !"-1".equalsIgnoreCase(getSelectedDocStatusId());
	}
	
	public Set getAddDocAttributeKeys() {
		return addDocAttributes.keySet();
	}
	
	public Integer getAddDocAttrSize() {
		if (addDocAttributes.isEmpty()) {
			return new Integer(0);
		} 

		return new Integer(addDocAttributes.size());
	}

	public boolean isHitsFound() {
		return hitsFound;
	}

	public boolean isSearching() {
		return searching;
	}

	public void setHitsFound(boolean b) {
		hitsFound = b;
	}

	public void setSearching(boolean b) {
		searching = b;
	}

	public Integer getHitsCount() {
		return hitsCount;
	}

	public void setHitsCount(Integer i) {
		hitsCount = i;
	}

	public List getResults() {
		return results;
	}

	public void setResults(List list) {
		results = list;
	}

	public Integer getPageCount() {
		return pageCount;
	}

	public void setPageCount(Integer i) {
		pageCount = i;
	}
	
	public Integer[] getPagesIndex() {
		Integer resultsPerPage = new Integer(getSelectedNumberOfResultsPerPage());
		Integer pagesCount = new Integer(((getHitsCount().intValue() % resultsPerPage.intValue()) == 0)
										 ? (getHitsCount().intValue() / resultsPerPage.intValue())
										 : ((getHitsCount().intValue() / resultsPerPage.intValue()) + 1));
		Integer[] pagesIndex = new Integer[pagesCount.intValue()];

		for (int i = 0; i < pagesIndex.length; i++) {
			pagesIndex[i] = new Integer(i + 1);
		}
		
		return pagesIndex;
	}
	
	public boolean isSearchAction(HttpServletRequest request) {
		boolean b1 = request.getParameter("action.searchDocuments.do") != null &&
					 (!isEmpty(getSearchInAnyField())  ||
					  !isEmpty(getSearchInFullText()) ||
					  !isEmpty(getSearchForCreationDateFrom()) ||
					  !isEmpty(getSearchForCreationDateUntil()) ||
					  !isEmpty(getSearchForDynaAttributeNames()) ||
					  !isEmpty(getSearchForDynaAttributeValues()) ||
					  !isEmpty(getSearchForFilename()) ||
					  !isEmpty(getSearchForTitle()) ||
					  !isEmpty(getSearchForKeywords()) ||
					  !isEmpty(getSearchForDescription()) ||
					  !isEmpty(getSearchForAuthor()) ||
					  !isEmpty(getSearchForPublisher()) ||
					  isSearchedForAddDocAttributes() ||
					  isSearchedDocClasses() ||
					  isSearchedDocStatus());
		boolean b2 = request.getParameter("searchInAnyField") != null  && !isEmpty(getSearchInAnyField());
		boolean b3 = request.getParameter("searchInFullText") != null  && !isEmpty(getSearchInFullText());
		boolean b4 = request.getParameter("searchForCreationDateFrom") != null && !isEmpty(getSearchForCreationDateFrom());
		boolean b5 = request.getParameter("searchForCreationDateUntil") != null && !isEmpty(getSearchForCreationDateUntil());
		boolean b6 = request.getParameter("searchForDynaAttributeNames") != null && !isEmpty(getSearchForDynaAttributeNames());
		boolean b7 = request.getParameter("searchForDynaAttributeValues") != null && !isEmpty(getSearchForDynaAttributeValues());
		boolean b8 = request.getParameter("searchForFilename") != null && !isEmpty(getSearchForFilename());
		boolean b9 = request.getParameter("searchForTitle") != null && !isEmpty(getSearchForTitle());
		boolean b10 = request.getParameter("searchForKeywords") != null && !isEmpty(getSearchForKeywords());
		boolean b11 = request.getParameter("searchForDescription") != null && !isEmpty(getSearchForDescription());
		boolean b12 = request.getParameter("searchForAuthor") != null && !isEmpty(getSearchForAuthor());
		boolean b13 = request.getParameter("searchForPublisher") != null && !isEmpty(getSearchForPublisher());
		boolean b14 = isSearchedForAddDocAttributes();
		boolean b15 = isSearchedDocClasses();
		boolean b16 = isSearchedDocStatus();
		boolean b17 = isQuickSearchAction(request);

		return b1 || b2 || b3 || b4 || b5 || b6 || b7 || b8 || b9 || b10 || b11 || b12 || b13 || b14 || b15 || b16 || b17;
	}
	
	public boolean isQuickSearchAction(HttpServletRequest request) {
		return request.getParameter("searchFromHereText") != null;
	}
	
	public String getSearchOptions() {
		String query = "";
		String separator1 = " &&";
		String separator2 = "&";
		query += separator1 + "selectedSortResults=" + getSelectedSortResults();
		query += separator2 + "selectedResultLimitation=" + getSelectedSearchResultLimitation();
		query += separator2 + "selectedCategoryId=" + getSelectedCategoryId();
		query += separator2 + "validFrom=" + getValidFrom();
		query += separator2 + "validUntil=" + getValidUntil();
		
		return query;
	}
	
	public String getSearchQuery() {
		String searchQuery = "";
		String searchInAnyField = getSearchInAnyField();
		String searchInFullText = getSearchInFullText();
		String searchForCreationDateFrom = getSearchForCreationDateFrom();
		String searchForCreationDateUntil = getSearchForCreationDateUntil();
		String searchForDynaAttributeNames = getSearchForDynaAttributeNames();
		String searchForDynaAttributeValues = getSearchForDynaAttributeValues();
		String searchForFilename = getSearchForFilename();
		String searchForTitle = getSearchForTitle();
		String searchForKeywords = getSearchForKeywords();
		String searchForDescription = getSearchForDescription();
		String searchForAuthor = getSearchForAuthor();
		String searchForPublisher = getSearchForPublisher();
		String selectedDocClassId = getSelectedDocClassId();
		String selectedDocStatusId = getSelectedDocStatusId();
		String booleanAND = " && ";
		HashMap addDocAttributes = getAddDocAttributes();
		int    linkCount = 0;

		//Lucenekonforme-Suchanfrage aus der gestellten Suchanfrage erstellen 
		if (!isEmpty(searchInFullText)) {
			linkCount++;
			
			if (linkCount > 1) {
				searchQuery += (booleanAND + "contents:(" + searchInFullText + ")");
			} else {
				searchQuery += ("contents:(" + searchInFullText + ")");
			}
		}

		if (!isEmpty(searchForCreationDateFrom) && !isEmpty(searchForCreationDateUntil)) {
			linkCount++;
			
			if (linkCount > 1) {
				searchQuery += (booleanAND + "creationDate:[" + DateTools.dateToString(getCreationDateFrom(), Resolution.MILLISECOND) + " TO " + DateTools.dateToString(getCreationDateUntil(), Resolution.MILLISECOND) + "]");
			} else {
				searchQuery += ("creationDate:[" + DateTools.dateToString(getCreationDateFrom(), Resolution.MILLISECOND) + " TO " + DateTools.dateToString(getCreationDateUntil(), Resolution.MILLISECOND) + "]");
			}
		} else if (!isEmpty(searchForCreationDateFrom) && isEmpty(searchForCreationDateUntil)) {
			linkCount++;
			
			if (linkCount > 1) {
				searchQuery += (booleanAND + "creationDate:[" + DateTools.dateToString(getCreationDateFrom(), Resolution.MILLISECOND) + " TO " + DateTools.dateToString(DateUtils.MAX_DATE_FOR_LUCENE, Resolution.MILLISECOND) + "]");
			} else {
				searchQuery += ("creationDate:[" + DateTools.dateToString(getCreationDateFrom(), Resolution.MILLISECOND) + " TO " + DateTools.dateToString(DateUtils.MAX_DATE_FOR_LUCENE, Resolution.MILLISECOND) + "]");
			}
		} else if (isEmpty(searchForCreationDateFrom) && !isEmpty(searchForCreationDateUntil)) {
			linkCount++;
			
			if (linkCount > 1) {
				searchQuery += (booleanAND + "creationDate:[" + DateTools.dateToString(DateUtils.MIN_DATE_FOR_LUCENE, Resolution.MILLISECOND) + " TO " + DateTools.dateToString(getCreationDateUntil(), Resolution.MILLISECOND) + "]");
			} else {
				searchQuery += ("creationDate:[" + DateTools.dateToString(DateUtils.MIN_DATE_FOR_LUCENE, Resolution.MILLISECOND) + " TO " + DateTools.dateToString(getCreationDateUntil(), Resolution.MILLISECOND) + "]");
			}
		}

		if (!isEmpty(searchForDynaAttributeNames)) {
			linkCount++;
			
			if (linkCount > 1) {
				searchQuery += (booleanAND + "dynaattributenames:(" + searchForDynaAttributeNames + ")");
			} else {
				searchQuery += ("dynaattributenames:(" + searchForDynaAttributeNames + ")");
			}
		}

		if (!isEmpty(searchForDynaAttributeValues)) {
			linkCount++;
			
			if (linkCount > 1) {
				searchQuery += (booleanAND + "dynaattributevalues:(" + searchForDynaAttributeValues + ")");
			} else {
				searchQuery += ("dynaattributevalues:(" + searchForDynaAttributeValues + ")");
			}
		}

		if (!isEmpty(searchForFilename)) {
			linkCount++;
			
			if (linkCount > 1) {
				searchQuery += (booleanAND + "name:(" + searchForFilename + ")");
			} else {
				searchQuery += ("name:(" + searchForFilename + ")");
			}
		}

		if (!isEmpty(searchForTitle)) {
			linkCount++;
			
			if (linkCount > 1) {
				searchQuery += (booleanAND + "title:(" + searchForTitle + ")");
			} else {
				searchQuery += ("title:(" + searchForTitle + ")");
			}
		}

		if (!isEmpty(searchForKeywords)) {
			linkCount++;
			
			if (linkCount > 1) {
				searchQuery += (booleanAND + "keywords:(" + searchForKeywords + ")");
			} else {
				searchQuery += ("keywords:(" + searchForKeywords + ")");
			}
		}

		if (!isEmpty(searchForDescription)) {
			linkCount++;
			
			if (linkCount > 1) {
				searchQuery += (booleanAND + "description:(" + searchForDescription + ")");
			} else {
				searchQuery += ("description:(" + searchForDescription + ")");
			}
		}

		if (!isEmpty(searchForAuthor)) {
			linkCount++;
			
			if (linkCount > 1) {
				searchQuery += (booleanAND + "authorname:(" + searchForAuthor + ")");
			} else {
				searchQuery += ("authorname:(" + searchForAuthor + ")");
			}
		}

		if (!isEmpty(searchForPublisher)) {
			linkCount++;
			
			if (linkCount > 1) {
				searchQuery += (booleanAND + "publishername:(" + searchForPublisher + ")");
			} else {
				searchQuery += ("publishername:(" + searchForPublisher + ")");
			}
		}

		if (!isEmpty(selectedDocClassId) && !"-1".equals(selectedDocClassId)) {
			linkCount++;
			
			if (!"*".equals(selectedDocClassId)) {
				selectedDocClassId = StringUtils.encodeToLetter(Integer.valueOf(selectedDocClassId));
			}
			
			if (linkCount > 1) {
				searchQuery += (booleanAND + "docClassId:(classid" + selectedDocClassId + ")");
			} else {
				searchQuery += ("docClassId:(classid" + selectedDocClassId + ")");
			}
		}

		if (!isEmpty(selectedDocStatusId) && !"-1".equals(selectedDocStatusId)) {
			linkCount++;
			
			if (!"*".equals(selectedDocStatusId)) {
				selectedDocStatusId = StringUtils.encodeToLetter(Integer.valueOf(selectedDocStatusId));
			}
			
			if (linkCount > 1) {
				searchQuery += (booleanAND + "docStatusId:(statusid" + selectedDocStatusId + ")");
			} else {
				searchQuery += ("docStatusId:(statusid" + selectedDocStatusId + ")");
			}
		}

		if (!addDocAttributes.isEmpty()) {
			Iterator itKeys = addDocAttributes.keySet().iterator();
			
			while ( itKeys.hasNext() ) {
				String fieldName = (String)itKeys.next();
				String fieldValue = (String)addDocAttributes.get(fieldName);
				
				if (!isEmpty(fieldValue)) {
					linkCount++;

					if (linkCount > 1) {
						searchQuery += (booleanAND + fieldName + ":(" + fieldValue + ")");
					} else {
						searchQuery += (fieldName + ":(" + fieldValue + ")");
					}
				}
			}
		}

		if (!isEmpty(searchInAnyField)) {
			linkCount++;
			
			if (linkCount > 1) {
				searchQuery += (booleanAND + searchInAnyField);
			} else {
				searchQuery += searchInAnyField;
			}
		}

		return searchQuery;
	}
	
	public Integer getStartIndex() {
		return startIndex;
	}

	public void setStartIndex(Integer integer) {
		startIndex = integer;
	}
	
    public String getCategoryPath() {
        VKCCategoryAbsPath cap = null;
        Integer categoryId = null;
        
        categoryId = Integer.valueOf(getSelectedCategoryId());
        
        try {
            cap = VKCCategorySerializer.getCategoryAbsPath(categoryId);
        } catch (DBException e) {
            cap = new VKCCategoryAbsPath();
        }
        
        return cap.getAbsolutePathString();
    }
    
	public List getDocumentClasses() {
		return VKCDocumentClassSerializer.getDocumentClasses();
	}

	public List getDocumentStatus() {
		return VKCDocumentStatusSerializer.getDocumentStati();
	}

	public List getDocumentTypes() {
        List documentTypes = VKCDocumentTypeSerializer.getDocumentTypes();
        
        for (Iterator iter = documentTypes.iterator() ; iter.hasNext() ;) {
            VKCDocumentType type = (VKCDocumentType)iter.next();
            
            if ("TDF".equals(type.getExtension())) {
                iter.remove();
            }
        }

        DocumentTypeSortFactory.sort(documentTypes, DocumentTypeSortFactory.SORT_BY_EXTENSION_UP);
		
        return documentTypes;
	}

	public String getSelectedCategoryId() {
	    return selectedCategoryId;
	}
	
	public String getSelectedDocClassId() {
		return selectedDocClassId;
	}

	public String getSelectedDocStatusId() {
		return selectedDocStatusId;
	}

	public String getSearchForCreationDateFrom() {
		return searchForCreationDateFrom;
	}

	public String getSearchForCreationDateUntil() {
		return searchForCreationDateUntil;
	}

	public String getValidFrom() {
		return validFrom;
	}

	public String getValidUntil() {
		return validUntil;
	}

	public Date getCreationDateFrom() {
		if (isEmpty(getSearchForCreationDateFrom())) {
			return null;
		} 

		Date d = DateUtils.parseDate(getSearchForCreationDateFrom());
		
		return d;
	}

	public Date getCreationDateUntil() {
		if (isEmpty(getSearchForCreationDateUntil())) {
			return null;
		} 
		
		Date d = DateUtils.parseDate(getSearchForCreationDateUntil());
		Calendar c = Calendar.getInstance();
		c.setTime(d);
		c.set(Calendar.HOUR_OF_DAY, 23);
		c.set(Calendar.MINUTE, 59);
		c.set(Calendar.SECOND, 59);
		
		return c.getTime();
	}

	public Date getFrom() {
		if (isEmpty(getValidFrom())) {
			return null;
		} 

		Date d = DateUtils.parseDate(getValidFrom());
		
		return d;
	}

	public Date getUntil() {
		if (isEmpty(getValidUntil())) {
			return null;
		} 
		
		Date d = DateUtils.parseDate(getValidUntil());
		Calendar c = Calendar.getInstance();
		c.setTime(d);
		c.set(Calendar.HOUR_OF_DAY, 23);
		c.set(Calendar.MINUTE, 59);
		c.set(Calendar.SECOND, 59);
		
		return c.getTime();
	}

	public void setSelectedCategoryId(String s) {
		selectedCategoryId = StringUtils.normalize(s);
	}

	public void setSelectedDocClassId(String s) {
		selectedDocClassId = StringUtils.normalize(s);
	}

	public void setSelectedDocStatusId(String s) {
		selectedDocStatusId = StringUtils.normalize(s);
	}

	public void setSearchForCreationDateFrom(String s) {
		searchForCreationDateFrom = StringUtils.normalize(s);
	}

	public void setSearchForCreationDateUntil(String s) {
		searchForCreationDateUntil = StringUtils.normalize(s);
	}

	public void setValidFrom(String s) {
		validFrom = StringUtils.normalize(s);
	}

	public void setValidUntil(String s) {
		validUntil = StringUtils.normalize(s);
	}

	public Integer[] getShowDocuments() {
		return showDocuments;
	}

	public void setShowDocuments(Integer[] list) {
		showDocuments = list;
	}

	public boolean getShowDocs(int i) {
		List ids = Arrays.asList(getShowDocuments());

		return ids.contains(new Integer(i));
	}

	public Integer[] getShowDocumentDetails() {
		return showDocumentDetails;
	}

	public void setShowDocumentDetails(Integer[] list) {
		showDocumentDetails = list;
	}

	public boolean getShowDocDetails(int i) {
		List ids = Arrays.asList(getShowDocumentDetails());
		
		return ids.contains(new Integer(i));
	}

	public Integer getSelectedId() {
		return selectedId;
	}

	public void setSelectedId(Integer integer) {
		selectedId = integer;
	}
	
	public String getAttributeKeyName(String key) throws DBException {
	    if (!isEmpty(key)) {
	        if (getAllAddDocAttributes().containsKey(key)) {
	            return ((VKCAddAttribute)getAllAddDocAttributes().get(key)).getName();
	        }
	    }
	    
	    return key;
	}
}