/*
 * $Id: VKCSearchQuery.java,v 1.33 2008/02/12 09:39:47 korowa Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: VKCSearchQuery.java,v $
 * Revision 1.33  2008/02/12 09:39:47  korowa
 * + Eine Möglichkeit für den Benutzer hinzugefügt die Emailsart auszuwählen (HTML oder Plaintext)
 * + Betreff für den Messenger der als Emailsubject bei Benachrichtigung übers erscheinen von VKC Dokumenten verschickt wird.
 *
 * Revision 1.32  2006/07/13 23:15:44  marbobo
 * + TDF-Format aus der Auswahlbox entfernt
 * + Dokumentformate sortiert
 *
 * Revision 1.31  2006/05/27 18:34:48  marbobo
 * + Neueste Lucene-Version eingebaut
 *
 * Revision 1.30  2006/03/15 12:39:24  marbobo
 * + Refactoring
 *
 * Revision 1.29  2006/03/09 01:27:22  marbobo
 * + Lokalisierung vervollständigt
 *
 * Revision 1.28  2005/09/05 22:41:28  marbobo
 * + Bugfixes
 *
 * Revision 1.27  2005/09/05 13:54:27  marbobo
 * +Suche nach Metadaten-Attribute (Erstellungsdatum) für Dokumente implementiert
 *
 * Revision 1.26  2005/02/20 16:57:27  marbobo
 * + Beim Speichern der Entities in die Datenbank wird sichergestellt
 *    dass Unicode-Zeichen in Kodierterform (als &#xxxxx;) gespeichert werden
 *
 * Revision 1.25  2005/02/04 22:06:36  marbobo
 * + Verwenden der Unicodefilter-Methode
 *
 * Revision 1.24  2004/11/09 20:14:58  marbobo
 * + Suche nach Herausgeber
 *
 * Revision 1.23  2004/10/06 12:33:38  marbobo
 * + Suche nach Globalen Dokument-Attributen korrigiert
 *
 * Revision 1.22  2004/10/05 17:59:50  marbobo
 * + Suche nach Globalen Dokument-Attributen überarbeitet
 *
 * Revision 1.21  2004/09/15 14:18:56  marbobo
 * + Volltextsuche korrigiert
 * + Suche über alle Felder
 *
 * Revision 1.20  2004/09/03 00:42:43  marbobo
 * + Kategorieauswahl über ein Explorer für die Suche eingebaut
 *
 * Revision 1.19  2004/08/26 22:10:48  marbobo
 * + Bugfix
 *
 * Revision 1.18  2004/08/20 18:02:24  marbobo
 * + kleine Änderungen und Bugfix in getLocalizedHTMLString()
 *
 * Revision 1.17  2004/08/20 12:38:31  koppy
 * + queryId, userId, getLocalizedASCIIString(...)
 *
 * Revision 1.16  2004/07/20 08:18:23  jonyp
 * added copyright info + cvs log
 *
 */
package vkc.db.entities;

import java.io.Serializable;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.Vector;

import org.apache.lucene.document.DateTools;
import org.apache.lucene.document.DateTools.Resolution;
import org.apache.struts.util.MessageResources;

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.util.DateUtils;
import vkc.util.StringUtils;
import vkc.util.VKCCategoryAbsPath;
import vkc.util.VKCStringUtils;
import vkc.util.sort.DocumentTypeSortFactory;

public class VKCSearchQuery implements Serializable{
    private Integer queryId							= null;
    private Integer userId							= null;
	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  selectedResultLimitation		= "*";
	private String  selectedCategoryId				= String.valueOf(VKCCategory.ROOT_CATEGORY_ID);
	private String  selectedDocClassId				= "-1";
	private String  selectedDocStatusId				= "-1";
	private String  validFrom						= "";
	private String  validUntil						= "";
    private String  subjectForNotification          = "";

	private HashMap addDocAttributes				= new HashMap();
    private HashMap allAddDocAttributes				= null;
	
	public VKCSearchQuery() {
		List addAttributes = new ArrayList();
		
		try {
			addAttributes = new ArrayList(VKCAddAttributeSerializer.getAllAddDocAttributes());
		} catch ( DBException e ) {
			addAttributes = new ArrayList();
		}

		if (!addAttributes.isEmpty()) {		
			allAddDocAttributes = new HashMap();
			
		    for (int i = 0; i < addAttributes.size(); i++) {
				VKCAddAttribute addAttr = (VKCAddAttribute)addAttributes.get(i);
                setAddDocAttrValue("adddocattrId_" + addAttr.getAttrId(), "");
                allAddDocAttributes.put("adddocattrId_" + addAttr.getAttrId(), addAttr);
			}
		}
	}
	
	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 getAddDocAttributes().get(key);
	}

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

	public Set getAddDocAttributeKeys() {
		return getAddDocAttributes().keySet();
	}
	
	public Integer getAddDocAttrSize() {
		if (getAddDocAttributes().isEmpty()) {
			return new Integer(0);
		} 

		return new Integer(getAddDocAttributes().size());
	}
	
	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 getLocalizedHTMLString(MessageResources resources, Locale locale, boolean renderDate, boolean renderDisplayOptions) throws DBException { 
		if (isEmpty()) {
		    return resources.getMessage(locale, "vkc.searchquery.empty");
		}
		
		String s = "";
		
		String tableTagOpen = "<table width=\"100%\">";
		String tableTagClose = "</table>";
		String rowTagOpen = "<tr>";
		String rowTagClose = "</tr>";
		String columnTagOpen = "<td>";
		String columnTagNowrapOpen = "<td nowrap=\"nowrap\">";
		String columnTagLongOpen = "<td width=\"100%\">";
		String columnTagClose = "</td>";
		String boldTagOpen = "<b>";
		String boldTagClose = "</b>";
		String space = "&nbsp;";
		String prefix = resources.getMessage(locale, "vkc.search.for");
		String prefix1 = resources.getMessage(locale, "vkc.search.to");
	
		HashMap sortList = new HashMap();
		sortList.put("0", "vkc.search.sortResults.ascendingByScore");
		sortList.put("1", "vkc.search.sortResults.descendingByScore");
		sortList.put("6", "vkc.search.sortResults.ascendingByCreationDate");
		sortList.put("7", "vkc.search.sortResults.descendingByCreationDate");
		sortList.put("2", "vkc.search.sortResults.ascendingByPublishingDate");
		sortList.put("3", "vkc.search.sortResults.descendingByPublishingDate");
		sortList.put("4", "vkc.search.sortResults.ascendingByAuthor");
		sortList.put("5", "vkc.search.sortResults.descendingByAuthor");

		String find = resources.getMessage(locale, "vkc.search.searchFor");
		String restrict = resources.getMessage(locale, "vkc.search.restrict");
		String display = resources.getMessage(locale, "vkc.search.display");
		String publication = resources.getMessage(locale, "vkc.search.publication");
		String anyfieldKey = resources.getMessage(locale, "vkc.search.searchInAnyField");
		String fulltextKey = resources.getMessage(locale, "vkc.search.searchInFullText");
		String dynaNameKey = resources.getMessage(locale, "vkc.search.searchForDynaAttributeNames");
		String dynaValueKey = resources.getMessage(locale, "vkc.search.searchForDynaAttributeValues");
		String filenameKey = resources.getMessage(locale, "vkc.search.searchForFilename");
		String titleKey = resources.getMessage(locale, "vkc.search.searchForTitle");
		String keywordsKey = resources.getMessage(locale, "vkc.search.searchForKeywords");
		String descriptionKey = resources.getMessage(locale, "vkc.search.searchForDescription");
		String authorKey = resources.getMessage(locale, "vkc.search.searchForAuthor");
		String publisherKey = resources.getMessage(locale, "vkc.search.searchForPublisher");
		String docClassKey = resources.getMessage(locale, "vkc.search.document.class");
		String docStatusKey = resources.getMessage(locale, "vkc.search.document.status");
		String sortKey = resources.getMessage(locale, "vkc.search.sortResults");
		String limitationKey = resources.getMessage(locale, "vkc.search.searchResultLimitation");
		String categoryPathKey = resources.getMessage(locale, "vkc.search.categorypath");
		String creationDateKey = resources.getMessage(locale, "vkc.search.creationdate");
		String creationDateFromKey = resources.getMessage(locale, "vkc.search.from");
		String creationDateUntilKey = resources.getMessage(locale, "vkc.search.until");
		String validFromKey = resources.getMessage(locale, "vkc.search.from");
		String validUntilKey = resources.getMessage(locale, "vkc.search.until");

		String anyfield = getSearchInAnyField();
		String fulltext = getSearchInFullText();
		String dynaName = getSearchForDynaAttributeNames();
		String dynaValue = getSearchForDynaAttributeValues();
		String filename = getSearchForFilename();
		String title = getSearchForTitle();
		String keywords = getSearchForKeywords();
		String description = getSearchForDescription();
		String author = getSearchForAuthor();
		String publisher = getSearchForPublisher();
		String docClass = "";
		String docStatus = "";
		String creationDateFrom = (StringUtils.isEmpty(getSearchForCreationDateFrom())) ? "-" : getSearchForCreationDateFrom();
		String creationDateUntil = (StringUtils.isEmpty(getSearchForCreationDateUntil())) ? "-" : getSearchForCreationDateUntil();

		String sort = resources.getMessage(locale, (String)sortList.get(getSelectedSortResults()));
		String limitation = "";
		String categoryPath = getCategoryPath();
		String validFrom = (StringUtils.isEmpty(getValidFrom())) ? "-" : getValidFrom();
		String validUntil = (StringUtils.isEmpty(getValidUntil())) ? "-" : getValidUntil();

		if (StringUtils.isEmpty(getSelectedDocClassId()) || "-1".equals(getSelectedDocClassId())) {
			docClass = "";
		} else if ("*".equals(getSelectedDocClassId())) {
			docClass = resources.getMessage(locale, "vkc.search.docClassId.all");
		} else {
			docClass = resources.getMessage(locale, VKCDocumentClassSerializer.getDocumentClass(Integer.valueOf(getSelectedDocClassId())).getNameKey());
		}

		if (StringUtils.isEmpty(getSelectedDocStatusId()) || "-1".equals(getSelectedDocStatusId())) {
			docStatus = "";
		} else if ("*".equals(getSelectedDocStatusId())) {
			docStatus = resources.getMessage(locale, "vkc.search.docStatusId.all");
		} else {
			docStatus = resources.getMessage(locale, VKCDocumentStatusSerializer.getDocumentStatus(Integer.valueOf(getSelectedDocStatusId())).getDescriptionKey());
		}

		if ("*".equals(getSelectedResultLimitation())) {
			limitation = resources.getMessage(locale, "vkc.search.searchResultLimitation.noLimitation");
		} else {
			limitation = VKCDocumentTypeSerializer.getDocumentTypeByExtension(getSelectedResultLimitation()).getExtensionLabel();
		}
	
		int count = 0;
	
		s += tableTagOpen;

		s += rowTagOpen;
		s += columnTagOpen;

		s += tableTagOpen;

		if (!StringUtils.isEmpty(anyfield)) {
			s += rowTagOpen;
			s += columnTagNowrapOpen + ((count != 0) ? space : VKCStringUtils.filterUnicodeChars(find)) + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(anyfieldKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(anyfield) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;

			count++;
		}
	
		if (!StringUtils.isEmpty(fulltext)) {
			s += rowTagOpen;
			s += columnTagNowrapOpen + ((count != 0) ? space : VKCStringUtils.filterUnicodeChars(find)) + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(fulltextKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(fulltext) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;

			count++;
		}
	
		if (!StringUtils.isEmpty( dynaName ) ) {
			s += rowTagOpen;
			s += columnTagNowrapOpen + ((count != 0) ? space : VKCStringUtils.filterUnicodeChars(find)) + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(dynaNameKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(dynaName) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;

			count++;
		}
	
		if (!StringUtils.isEmpty(dynaValue)) {
			s += rowTagOpen;
			s += columnTagNowrapOpen + ((count != 0) ? space : VKCStringUtils.filterUnicodeChars(find)) + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(dynaValueKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(dynaValue) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;

			count++;
		}
	
		if (!StringUtils.isEmpty(filename)) {
			s += rowTagOpen;
			s += columnTagNowrapOpen + ((count != 0) ? space : VKCStringUtils.filterUnicodeChars(find)) + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(filenameKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(filename) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;

			count++;
		}
	
		if (!StringUtils.isEmpty(title)) {
			s += rowTagOpen;
			s += columnTagNowrapOpen + ((count != 0) ? space : VKCStringUtils.filterUnicodeChars(find)) + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(titleKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(title) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;

			count++;
		}
	
		if (!StringUtils.isEmpty(keywords)) {
			s += rowTagOpen;
			s += columnTagNowrapOpen + ((count != 0) ? space : VKCStringUtils.filterUnicodeChars(find)) + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(keywordsKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(keywords) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;

			count++;
		}
	
		if (!StringUtils.isEmpty(description)) {
			s += rowTagOpen;
			s += columnTagNowrapOpen + ((count != 0) ? space : VKCStringUtils.filterUnicodeChars(find)) + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(descriptionKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(description) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;

			count++;
		}
	
		if (!StringUtils.isEmpty(author)) {
			s += rowTagOpen;
			s += columnTagNowrapOpen + ((count != 0) ? space : VKCStringUtils.filterUnicodeChars(find)) + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(authorKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(author) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;

			count++;
		}
	
		if (!StringUtils.isEmpty(publisher)) {
			s += rowTagOpen;
			s += columnTagNowrapOpen + ((count != 0) ? space : VKCStringUtils.filterUnicodeChars(find)) + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(publisherKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(publisher) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;

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

				if (!StringUtils.isEmpty(fieldValue)) {
					s += rowTagOpen;
					s += columnTagNowrapOpen + ((count != 0) ? space : VKCStringUtils.filterUnicodeChars(find)) + columnTagClose;
					s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(prefix) + space + VKCStringUtils.filterUnicodeChars(getAttributeKeyName(fieldName)) + boldTagClose + columnTagClose;
					s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(fieldValue) + columnTagClose;
					s += columnTagNowrapOpen + space + columnTagClose;
					s += rowTagClose;

					count++;
				}
			}
		}

		if (!StringUtils.isEmpty(getSearchForCreationDateFrom()) || !StringUtils.isEmpty(getSearchForCreationDateUntil())) {
			s += rowTagOpen;
			s += columnTagNowrapOpen + ((count != 0) ? space : VKCStringUtils.filterUnicodeChars(find)) + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(prefix) + space + VKCStringUtils.filterUnicodeChars(creationDateKey) + space + VKCStringUtils.filterUnicodeChars(creationDateFromKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(creationDateFrom) + space + space + boldTagOpen + VKCStringUtils.filterUnicodeChars(creationDateUntilKey) + boldTagClose + space + VKCStringUtils.filterUnicodeChars(creationDateUntil) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;

			count++;
		}
	
		if (!StringUtils.isEmpty(docClass)) {
			s += rowTagOpen;
			s += columnTagNowrapOpen + ((count != 0) ? space : VKCStringUtils.filterUnicodeChars(find)) + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(prefix) + space + VKCStringUtils.filterUnicodeChars(docClassKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(docClass) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;

			count++;
		}
	
		if (!StringUtils.isEmpty(docStatus)) {
			s += rowTagOpen;
			s += columnTagNowrapOpen + ((count != 0) ? space : VKCStringUtils.filterUnicodeChars(find)) + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(prefix) + space + VKCStringUtils.filterUnicodeChars(docStatusKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(docStatus) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;

			count++;
		}
	
		s += tableTagClose;

		s += columnTagClose;
		s += rowTagClose;

		s += rowTagOpen;
		s += columnTagOpen;

		s += tableTagOpen;

		if (renderDate) {
		    s += rowTagOpen;
			s += columnTagNowrapOpen + VKCStringUtils.filterUnicodeChars(restrict) + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(prefix) + space + VKCStringUtils.filterUnicodeChars(publication) + space + VKCStringUtils.filterUnicodeChars(validFromKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(validFrom) + space + space + boldTagOpen + VKCStringUtils.filterUnicodeChars(validUntilKey) + boldTagClose + space + VKCStringUtils.filterUnicodeChars(validUntil) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;    

			s += rowTagOpen;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(prefix1) + space + VKCStringUtils.filterUnicodeChars(categoryPathKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(categoryPath) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;

			s += rowTagOpen;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(prefix) + space + VKCStringUtils.filterUnicodeChars(limitationKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(limitation) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;
		} else {
			s += rowTagOpen;
			s += columnTagNowrapOpen + VKCStringUtils.filterUnicodeChars(restrict) + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(prefix1) + space + VKCStringUtils.filterUnicodeChars(categoryPathKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(categoryPath) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;

			s += rowTagOpen;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(prefix) + space + VKCStringUtils.filterUnicodeChars(limitationKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(limitation) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;
		}
		
		s += tableTagClose;

		s += columnTagClose;
		s += rowTagClose;

		if (renderDisplayOptions) {
			s += rowTagOpen;
			s += columnTagOpen;

			s += tableTagOpen;

			s += rowTagOpen;
			s += columnTagNowrapOpen + VKCStringUtils.filterUnicodeChars(display) + columnTagClose;
			s += columnTagNowrapOpen + boldTagOpen + VKCStringUtils.filterUnicodeChars(prefix) + space + VKCStringUtils.filterUnicodeChars(sortKey) + boldTagClose + columnTagClose;
			s += columnTagLongOpen + VKCStringUtils.filterUnicodeChars(sort) + columnTagClose;
			s += columnTagNowrapOpen + space + columnTagClose;
			s += rowTagClose;

			s += tableTagClose;

			s += columnTagClose;
			s += rowTagClose;
		}

		s += tableTagClose;
	
		return s;
	}
	
	public String getLocalizedASCIIString(MessageResources resources, Locale locale, boolean renderDate, boolean renderDisplayOptions) throws DBException { 
		if (isEmpty()) {
		    return resources.getMessage(locale, "vkc.searchquery.empty");
		}
		
		StringBuffer s = new StringBuffer();
		
		String lf = "\n";
		String space = " ";
		String prefix = resources.getMessage(locale, "vkc.search.for");
		String prefix1 = resources.getMessage(locale, "vkc.search.to");
	
		HashMap sortList = new HashMap();
		sortList.put("0", "vkc.search.sortResults.ascendingByScore");
		sortList.put("1", "vkc.search.sortResults.descendingByScore");
		sortList.put("6", "vkc.search.sortResults.ascendingByCreationDate");
		sortList.put("7", "vkc.search.sortResults.descendingByCreationDate");
		sortList.put("2", "vkc.search.sortResults.ascendingByPublishingDate");
		sortList.put("3", "vkc.search.sortResults.descendingByPublishingDate");
		sortList.put("4", "vkc.search.sortResults.ascendingByAuthor");
		sortList.put("5", "vkc.search.sortResults.descendingByAuthor");

		String find = resources.getMessage(locale, "vkc.search.searchFor");
		String restrict = resources.getMessage(locale, "vkc.search.restrict");
		String display = resources.getMessage(locale, "vkc.search.display");
		String publication = resources.getMessage(locale, "vkc.search.publication");
		String anyfieldKey = resources.getMessage(locale, "vkc.search.searchInAnyField");
		String fulltextKey = resources.getMessage(locale, "vkc.search.searchInFullText");
		String dynaNameKey = resources.getMessage(locale, "vkc.search.searchForDynaAttributeNames");
		String dynaValueKey = resources.getMessage(locale, "vkc.search.searchForDynaAttributeValues");
		String filenameKey = resources.getMessage(locale, "vkc.search.searchForFilename");
		String titleKey = resources.getMessage(locale, "vkc.search.searchForTitle");
		String keywordsKey = resources.getMessage(locale, "vkc.search.searchForKeywords");
		String descriptionKey = resources.getMessage(locale, "vkc.search.searchForDescription");
		String authorKey = resources.getMessage(locale, "vkc.search.searchForAuthor");
		String publisherKey = resources.getMessage(locale, "vkc.search.searchForPublisher");
		String docClassKey = resources.getMessage(locale, "vkc.search.document.class");
		String docStatusKey = resources.getMessage(locale, "vkc.search.document.status");
		String sortKey = resources.getMessage(locale, "vkc.search.sortResults");
		String limitationKey = resources.getMessage(locale, "vkc.search.searchResultLimitation");
		String categoryPathKey = resources.getMessage(locale, "vkc.search.categorypath");
		String creationDateKey = resources.getMessage(locale, "vkc.search.creationdate");
		String creationDateFromKey = resources.getMessage(locale, "vkc.search.from");
		String creationDateUntilKey = resources.getMessage(locale, "vkc.search.until");
		String validFromKey = resources.getMessage(locale, "vkc.search.from");
		String validUntilKey = resources.getMessage(locale, "vkc.search.until");

		String anyfield = getSearchInAnyField();
		String fulltext = getSearchInFullText();
		String dynaName = getSearchForDynaAttributeNames();
		String dynaValue = getSearchForDynaAttributeValues();
		String filename = getSearchForFilename();
		String title = getSearchForTitle();
		String keywords = getSearchForKeywords();
		String description = getSearchForDescription();
		String author = getSearchForAuthor();
		String publisher = getSearchForPublisher();
		String docClass = "";
		String docStatus = "";
		String creationDateFrom = (StringUtils.isEmpty(getSearchForCreationDateFrom())) ? "-" : getSearchForCreationDateFrom();
		String creationDateUntil = (StringUtils.isEmpty(getSearchForCreationDateUntil())) ? "-" : getSearchForCreationDateUntil();

		String sort = resources.getMessage(locale, (String)sortList.get(getSelectedSortResults()));
		String limitation = "";
		String categoryPath = getCategoryPath();
		String validFrom = (StringUtils.isEmpty(getValidFrom())) ? "-" : getValidFrom();
		String validUntil = (StringUtils.isEmpty(getValidUntil())) ? "-" : getValidUntil();

		if (StringUtils.isEmpty(getSelectedDocClassId()) || "-1".equals(getSelectedDocClassId())) {
			docClass = "";
		} else if ("*".equals(getSelectedDocClassId())) {
			docClass = resources.getMessage(locale, "vkc.search.docClassId.all");
		} else {
			docClass = resources.getMessage(locale, VKCDocumentClassSerializer.getDocumentClass(Integer.valueOf(getSelectedDocClassId())).getNameKey());
		}

		if (StringUtils.isEmpty(getSelectedDocStatusId()) || "-1".equals(getSelectedDocStatusId())) {
			docStatus = "";
		} else if ("*".equals(getSelectedDocStatusId())) {
			docStatus = resources.getMessage(locale, "vkc.search.docStatusId.all");
		} else {
			docStatus = resources.getMessage(locale, VKCDocumentStatusSerializer.getDocumentStatus(Integer.valueOf(getSelectedDocStatusId())).getDescriptionKey());
		}

		if ("*".equals(getSelectedResultLimitation())) {
			limitation = resources.getMessage(locale, "vkc.search.searchResultLimitation.noLimitation");
		} else {
			limitation = VKCDocumentTypeSerializer.getDocumentTypeByExtension(getSelectedResultLimitation()).getExtensionLabel();
		}
	
		int count = 0;
		
		String findSpace = StringUtils.fillUp("", ' ', find.length());

		if (!StringUtils.isEmpty(anyfield)) {
			formatQueryField(s, lf, find, anyfieldKey, anyfield, count, findSpace);

			count++;
		}
	
		if (!StringUtils.isEmpty(fulltext)) {
			formatQueryField(s, lf, find, fulltextKey, fulltext, count, findSpace);

			count++;
		}

		if (!StringUtils.isEmpty(dynaName)) {
		    formatQueryField(s, lf, find, dynaNameKey, dynaName, count, findSpace);
		    
			count++;
		}
	
		if (!StringUtils.isEmpty(dynaValue)) {
		    formatQueryField(s, lf, find, dynaValueKey, dynaValue, count, findSpace);
		    
			count++;
		}
	
		if (!StringUtils.isEmpty(filename)) {
		    formatQueryField(s, lf, find, filenameKey, filename, count, findSpace);

			count++;
		}
	
		if (!StringUtils.isEmpty(title)) {
		    formatQueryField(s, lf, find, titleKey, title, count, findSpace);
			
			count++;
		}
	
		if (!StringUtils.isEmpty(keywords)) {
		    formatQueryField(s, lf, find, keywordsKey, keywords, count, findSpace);
			
			count++;
		}
	
		if (!StringUtils.isEmpty(description)) {
		    formatQueryField(s, lf, find, descriptionKey, description, count, findSpace);

			count++;
		}
	
		if (!StringUtils.isEmpty(author)) {
		    formatQueryField(s, lf, find, authorKey, author, count, findSpace);

			count++;
		}
	
		if (!StringUtils.isEmpty(publisher)) {
		    formatQueryField(s, lf, find, publisherKey, publisher, count, findSpace);

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

				if (!StringUtils.isEmpty(fieldValue)) {
				    formatQueryField(s, lf, find, prefix + space + getAttributeKeyName(fieldName), fieldValue, count, findSpace);

					count++;
				}
			}
		}

		if (!StringUtils.isEmpty(getSearchForCreationDateFrom()) || !StringUtils.isEmpty(getSearchForCreationDateUntil())) {
		    formatQueryField(s, lf, restrict, prefix + space + creationDateKey + space + creationDateFromKey, creationDateFrom + space + creationDateUntilKey + space + creationDateUntil, count, findSpace);
			
			count++;
		}
		
		if (!StringUtils.isEmpty(docClass)) {
		    formatQueryField(s, lf, find, prefix + space + docClassKey, docClass, count, findSpace);

			count++;
		}
	
		if (!StringUtils.isEmpty(docStatus)) {
		    formatQueryField(s, lf, find, prefix + space + docStatusKey, docStatus, count, findSpace);
			
			count++;
		}
	
		//s.append(lf);
		String restrictSpace = StringUtils.fillUp(null, ' ', restrict.length());
		
		if (renderDate) {
		    //s.append(lf);
		    formatQueryField(s, lf, restrict, prefix + space + publication + space + validFromKey, validFrom + space + validUntilKey + space + validUntil, 0, restrictSpace);
			formatQueryField(s, lf, restrict, prefix1 + space + categoryPathKey, categoryPath, 1, restrictSpace);
			formatQueryField(s, lf, restrict, prefix + space + limitationKey, limitation, 2, restrictSpace);
		} else {
			formatQueryField(s, lf, restrict, prefix1 + space + categoryPathKey, categoryPath, 0, restrictSpace);
			formatQueryField(s, lf, restrict, prefix + space + limitationKey, limitation, 1, restrictSpace);
		}

		if (renderDisplayOptions) {
		    //s.append(lf);
		    String displaySpace = StringUtils.fillUp(null, ' ', display.length());
			
		    formatQueryField(s, lf, display, prefix + space + sortKey, sort, 0, displaySpace);
		}
	
		return s.toString();
	}
	

	/**
	 * formats a row for ascii representation
     * @param s
     * @param lf
     * @param desc
     * @param textKey
     * @param text
     * @param count
     * @param spacer
     */
    private void formatQueryField(StringBuffer s, String lf, String desc, String textKey, String text, int count, String spacer) {
        s.append((count != 0) ? spacer : desc).append(' ');
        s.append(textKey).append(':').append(' ');
        s.append(text).append(lf);
    }

    public Integer getCategoryId() {
        Integer categoryId = new Integer(VKCCategory.ROOT_CATEGORY_ID);
        
        if (!StringUtils.isEmpty(getSelectedCategoryId())) {
            categoryId = Integer.valueOf(getSelectedCategoryId());
        }
        
        return (categoryId.equals(new Integer(VKCCategory.ROOT_CATEGORY_ID))) ? null : categoryId;
    }
    
    public String getCategoryPath() {
        VKCCategoryAbsPath cap = null;
        Integer categoryId = new Integer(VKCCategory.ROOT_CATEGORY_ID);
        
        if (!StringUtils.isEmpty(getSelectedCategoryId())) {
            categoryId = Integer.valueOf(getSelectedCategoryId());
        }
        
        try {
            cap = VKCCategorySerializer.getCategoryAbsPath(categoryId);
        } catch (DBException e) {
            cap = new VKCCategoryAbsPath();
        }
        
        return cap.getAbsolutePathString();
    }
    
    public String getSearchForAuthor() {
		return searchForAuthor;
	}

    public String getSearchForPublisher() {
		return searchForPublisher;
	}

	public String getSearchForDescription() {
		return searchForDescription;
	}

	public String getSearchForDynaAttributeNames() {
		return searchForDynaAttributeNames;
	}

	public String getSearchForDynaAttributeValues() {
		return searchForDynaAttributeValues;
	}

	public String getSearchForKeywords() {
		return searchForKeywords;
	}

	public String getSearchForFilename() {
		return searchForFilename;
	}

	public String getSearchForTitle() {
		return searchForTitle;
	}

	public String getSearchInAnyField() {
		return searchInAnyField;
	}

	public String getSearchInFullText() {
		return searchInFullText;
	}

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

	public String getSelectedDocStatusId() {
		return selectedDocStatusId;
	}

	public String getSelectedResultLimitation() {
		return selectedResultLimitation;
	}

	public String getSelectedSortResults() {
		return selectedSortResults;
	}

	public HashMap getQueryElements() {
		HashMap elements = new HashMap();
		String query = getSearchQuery();
		
		if (!StringUtils.isEmpty(query)) {
			HashMap searchElements = getSearchElements();
			HashMap optionElements = getOptionElements();
			elements.putAll(searchElements);
			elements.putAll(optionElements);
		}
		
		return elements;
	}

	private HashMap getOptionElements() {
		HashMap elements = new HashMap();

		if (!StringUtils.isEmpty(getSelectedSortResults())) {
			elements.put("sortmode:(", "sortmode:(" + getSelectedSortResults() + ")");
		}

		if (!StringUtils.isEmpty(getSelectedResultLimitation())) {
			elements.put("resultlimitation:(", "resultlimitation:(" + getSelectedResultLimitation() + ")");
		}

		if (!StringUtils.isEmpty(getSelectedCategoryId())) {
			elements.put("categoryid:(", "categoryid:(" + getSelectedCategoryId() + ")");
		}

		if (!StringUtils.isEmpty(getValidFrom())) {
			elements.put("validFrom:(", "validFrom:(" + getValidFrom() + ")");
		}

		if (!StringUtils.isEmpty( getValidUntil())) {
			elements.put("validUntil:(", "validUntil:(" + getValidUntil() + ")");
		}

		return elements;
	}

	private HashMap getSearchElements() {
		HashMap elements = new HashMap();

		if (!StringUtils.isEmpty(getSearchInAnyField())) {
			elements.put("anyfield:(", "anyfield:(" + getSearchInAnyField() + ")");
		}

		if (!StringUtils.isEmpty(getSearchInFullText())) {
			elements.put("fulltext:(", "fulltext:(" + getSearchInFullText() + ")");
		}

		if (!StringUtils.isEmpty(getSearchForDynaAttributeNames())) {
			elements.put("dynaattributenames:(", "dynaattributenames:(" + getSearchForDynaAttributeNames() + ")");
		}

		if (!StringUtils.isEmpty(getSearchForDynaAttributeValues())) {
			elements.put("dynaattributevalues:(", "dynaattributevalues:(" + getSearchForDynaAttributeValues() + ")");
		}

		if (!StringUtils.isEmpty(getSearchForAuthor())) {
			elements.put("authorname:(", "authorname:(" + getSearchForAuthor() + ")");
		}
		
		if (!StringUtils.isEmpty(getSearchForPublisher())) {
			elements.put("publishername:(", "publishername:(" + getSearchForPublisher() + ")");
		}
		
		if (!StringUtils.isEmpty(getSearchForTitle())) {
			elements.put("title:(", "title:(" + getSearchForTitle() + ")");
		}

		if (!StringUtils.isEmpty(getSearchForKeywords())) {
			elements.put("keywords:(", "keywords:(" + getSearchForKeywords() + ")");
		}

		if (!StringUtils.isEmpty(getSearchForDescription())) {
			elements.put("description:(", "description:(" + getSearchForDescription() + ")");
		}

		if (!StringUtils.isEmpty(getSearchForFilename())) {
			elements.put("name:(", "name:(" + getSearchForFilename() + ")");
		}

		if (!StringUtils.isEmpty(getSearchForCreationDateFrom()) && !StringUtils.isEmpty(getSearchForCreationDateUntil())) {
			elements.put("creationDate:[", "creationDate:[" + DateTools.dateToString(getCreationDateFrom(), Resolution.MILLISECOND) + " TO " + DateTools.dateToString(getCreationDateUntil(), Resolution.MILLISECOND) + "]");
		} else if (!StringUtils.isEmpty(getSearchForCreationDateFrom()) && StringUtils.isEmpty(getSearchForCreationDateUntil())) {
			elements.put("creationDate:[", "creationDate:[" + DateTools.dateToString(getCreationDateFrom(), Resolution.MILLISECOND) + " TO " + DateTools.dateToString(DateUtils.MAX_DATE_FOR_LUCENE, Resolution.MILLISECOND) + "]");
		} else if (StringUtils.isEmpty(getSearchForCreationDateFrom()) && !StringUtils.isEmpty(getSearchForCreationDateUntil())) {
			elements.put("creationDate:[", "creationDate:[" + DateTools.dateToString(DateUtils.MIN_DATE_FOR_LUCENE, Resolution.MILLISECOND) + " TO " + DateTools.dateToString(getCreationDateUntil(), Resolution.MILLISECOND) + "]");
		}
		
		if (!StringUtils.isEmpty(getSelectedDocClassId())) {
			elements.put("docClassId:(", "docClassId:(" + getSelectedDocClassId() + ")");
		}

		if (!StringUtils.isEmpty(getSelectedDocStatusId())) {
			elements.put("docStatusId:(", "docStatusId:(" + getSelectedDocStatusId() + ")");
		}

		if (!getAddDocAttributes().isEmpty()) {
			Iterator itKeys = getAddDocAttributes().keySet().iterator();
			String separator = " && ";
			String value = "";
			
			while (itKeys.hasNext()) {
				String fieldName = (String)itKeys.next();
				String fieldValue = (String)getAddDocAttributes().get(fieldName);
				
				if (!StringUtils.isEmpty(fieldValue)) {
					if (!StringUtils.isEmpty(value)) {
						value += separator + fieldName + ":(" + fieldValue + ")";
					} else {
						value += fieldName + ":(" + fieldValue + ")";
					}
					
				}
			}
			
			if (!StringUtils.isEmpty(value)) {
				elements.put("adddocattributes:(", "adddocattributes:(" + value + ")");
			}
		}

		return elements;
	}

	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 (!StringUtils.isEmpty(searchInFullText)) {
			linkCount++;
			
			if (linkCount > 1) {
				searchQuery += (booleanAND + "contents:(" + searchInFullText + ")");
			} else {
				searchQuery += ("contents:(" + searchInFullText + ")");
			}
		}

		if (!StringUtils.isEmpty(searchForCreationDateFrom) && !StringUtils.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 (!StringUtils.isEmpty(searchForCreationDateFrom) && StringUtils.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 (StringUtils.isEmpty(searchForCreationDateFrom) && !StringUtils.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 (!StringUtils.isEmpty(searchForDynaAttributeNames)) {
			linkCount++;
			
			if (linkCount > 1) {
				searchQuery += (booleanAND + "dynaattributenames:(" + searchForDynaAttributeNames + ")");
			} else {
				searchQuery += ("dynaattributenames:(" + searchForDynaAttributeNames + ")");
			}
		}

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

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

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

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

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

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

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

		if (!StringUtils.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 (!StringUtils.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 (!StringUtils.isEmpty(fieldValue)) {
					linkCount++;

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

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

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

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

	public Date getUntil() {
		if (StringUtils.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 Date getCreationDateFrom() {
		if (StringUtils.isEmpty(getSearchForCreationDateFrom())) {
			return null;
		} 

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

	public Date getCreationDateUntil() {
		if (StringUtils.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 String getValidFrom() {
		return validFrom;
	}

	public String getValidUntil() {
		return validUntil;
	}

	public String getSearchForCreationDateFrom() {
		return searchForCreationDateFrom;
	}

	public String getSearchForCreationDateUntil() {
		return searchForCreationDateUntil;
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

	public void setSelectedResultLimitation(String string) {
		selectedResultLimitation = StringUtils.normalize(string);
	}

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

	public void setQueryElements(HashMap elements) {
		if (!elements.isEmpty()) {
			String[] fields = {"anyfield:(", "fulltext:(", "creationDate:[", "dynaattributenames:(", "dynaattributevalues:(", "authorname:(",
			        		   "publishername:(", "title:(", "keywords:(", "description:(", "name:(", "docClassId:(", "docStatusId:(",
							   "sortmode:(", "resultlimitation:(", "categoryid:(", "validFrom:(", "validUntil:("};
			String[] values = {"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""};

			for (int i = 0; i < fields.length; i++) {
				if (elements.containsKey(fields[i])) {
					String element = (String)elements.get(fields[i]);
					values[i] = element.substring(fields[i].length(), element.length() - 1);
				}
			}
			
			setSearchInAnyField(values[0]);
			setSearchInFullText(values[1]);
			
			if (!StringUtils.isEmpty(values[2])) {
				int index = values[2].indexOf("TO");
				
				if (index != -1) {
					String from = StringUtils.normalize(values[2].substring(0, index));
					String until = StringUtils.normalize(values[2].substring(index + "TO".length()));
					
					if (!DateTools.dateToString(DateUtils.MIN_DATE_FOR_LUCENE, Resolution.MILLISECOND).equalsIgnoreCase(from)) {
						try {
							setSearchForCreationDateFrom(DateUtils.getDD_MM_YYYY(DateTools.stringToDate(from)));
						} catch (ParseException e) {
							setSearchForCreationDateFrom("");
						}
					} else {
						setSearchForCreationDateFrom("");
					}
					
					if (!DateTools.dateToString(DateUtils.MAX_DATE_FOR_LUCENE, Resolution.MILLISECOND).equalsIgnoreCase(until)) {
						try {
							setSearchForCreationDateUntil(DateUtils.getDD_MM_YYYY(DateTools.stringToDate(until)));
						} catch (ParseException e) {
							setSearchForCreationDateUntil("");
						}
					} else {
						setSearchForCreationDateUntil("");
					}
				} else {
					setSearchForCreationDateFrom("");
					setSearchForCreationDateUntil("");
				}
			} else {
				setSearchForCreationDateFrom("");
				setSearchForCreationDateUntil("");
			}
			
			setSearchForDynaAttributeNames(values[3]);
			setSearchForDynaAttributeValues(values[4]);
			setSearchForAuthor(values[5]);
			setSearchForPublisher(values[6]);
			setSearchForTitle(values[7]);
			setSearchForKeywords(values[8]);
			setSearchForDescription(values[9]);
			setSearchForFilename(values[10]);
			setSelectedDocClassId(values[11]);
			setSelectedDocStatusId(values[12]);
			setSelectedSortResults(values[13]);
			setSelectedResultLimitation(values[14]);
			setSelectedCategoryId(values[15]);
			setValidFrom(values[16]);
			setValidUntil(values[17]);
			
			if (elements.containsKey("adddocattributes:(")) {
				String element = (String)elements.get("adddocattributes:(");
				String value = element.substring("adddocattributes:(".length(), element.length() - 1);
				String startTag = ":(";
				String endTag = ") && ";
				
				while (!StringUtils.isEmpty(value)) {
					String fieldName = "";
					String fieldValue = "";
					int startIndex = value.indexOf(startTag);
					int endIndex = -1;
					
					if (startIndex != -1) {
						fieldName = value.substring(0, startIndex);
						startIndex += startTag.length();
						endIndex = value.indexOf(endTag);

						if (endIndex != -1) {
							fieldValue = value.substring(startIndex, endIndex);
							endIndex += endTag.length();
						} else {
							endIndex = value.lastIndexOf(")");
							fieldValue = value.substring(startIndex, endIndex);
							endIndex += 1;
						}

						setAddDocAttrValue(fieldName, fieldValue);
						value = value.substring(endIndex, value.length());
					}
					
					value = value.trim();
				}
				
			}
			
		}
	}

	public String getQuery() {
		String query = getSearchQuery();
		
		if (!StringUtils.isEmpty(query)) {
			String separator1 = " &&";
			String separator2 = "&";
			query += separator1 + "selectedSortResults=" + getSelectedSortResults();
			query += separator2 + "selectedResultLimitation=" + getSelectedResultLimitation();
			query += separator2 + "selectedCategoryId=" + getSelectedCategoryId();
			query += separator2 + "validFrom=" + getValidFrom();
			query += separator2 + "validUntil=" + getValidUntil();
		}
		
		return query;
	}

	public void setQuery(String query) {
		if (!StringUtils.isEmpty(query)) {
			String separator = "&&";
			int index = query.lastIndexOf(separator);
			
			if (index > 0) {
			    String searchQuery = query.substring(0, index);
				index += separator.length();
				String options = query.substring(index, query.length());
				setSearchFields(searchQuery);
				setOptionFields(options);
			} else {
			    setSearchFields(query);
			}
			
		}
	}

	private void setOptionFields(String options) {
		String separator = "&";
		String value = "";
		String field1 = "selectedSortResults=";
		String field2 = "selectedResultLimitation=";
		String field3 = "selectedCategoryId=";
		String field4 = "validFrom=";
		String field5 = "validUntil=";
		int startIndex = field1.length();
		int endIndex = options.indexOf(separator);

		value = options.substring(startIndex, endIndex);
		setSelectedSortResults(value);

		options = options.substring(endIndex + 1, options.length());
		startIndex = field2.length();
		endIndex = options.indexOf(separator);

		value = options.substring(startIndex, endIndex);
		setSelectedResultLimitation(value);
		
		options = options.substring(endIndex + 1, options.length());
		startIndex = field3.length();
		endIndex = options.indexOf(separator);

		value = options.substring(startIndex, endIndex);
		setSelectedCategoryId(value);
		
		options = options.substring(endIndex + 1, options.length());
		startIndex = field4.length();
		endIndex = options.indexOf(separator);

		value = options.substring(startIndex, endIndex);
		setValidFrom(value);

		options = options.substring(endIndex + 1, options.length());
		startIndex = field5.length();
		endIndex = options.length();

		value = options.substring(startIndex, endIndex);
		setValidUntil(value);
	}

	private void setSearchFields(String searchQuery) {
		String separator = "&&";
		String tagEnd = ") ";
		String tagEnd1 = "] ";
		String[] fields = {"contents:(", "creationDate:[", "dynaattributenames:(", "dynaattributevalues:(", "authorname:(", "publishername:(", "title:(",
		        		   "keywords:(", "description:(", "name:(", "docClassId:(classid", "docStatusId:(statusid"};
		String[] values = {"", "", "", "", "", "", "", "", "", "", "", ""};
		
		for (int i = 0; i < fields.length; i++) {
			int startIndex = searchQuery.indexOf(fields[i]);
			int endIndex = searchQuery.indexOf(separator);
			
			if (startIndex != -1) {
				String tempTagEnd = tagEnd;
				
				if (fields[i].endsWith("[")) {
					tempTagEnd = tagEnd1;
				}
				
				int index1 = startIndex + fields[i].length();
				String value = searchQuery.substring(index1);
				int index2 = value.indexOf(tempTagEnd + separator);
				int endLength = tempTagEnd.length() + separator.length();
				
				if (index2 == -1) {
					index2 = value.indexOf(tempTagEnd);
					endLength = tempTagEnd.length();
				}
				
				value = value.substring(0, index2);
				endIndex = index1 + value.length() + endLength;
				values[i] = StringUtils.normalize(value);
				searchQuery = cutOut(searchQuery, startIndex, endIndex);
			}
		}
		
		setSearchInFullText(VKCStringUtils.filterUnicodeChars(values[0]));
		
		if (!StringUtils.isEmpty(values[1])) {
			int index = values[1].indexOf("TO");
			
			if (index != -1) {
				String from = StringUtils.normalize(values[1].substring(0, index));
				String until = StringUtils.normalize(values[1].substring(index + "TO".length()));
				
				if (!DateTools.dateToString(DateUtils.MIN_DATE_FOR_LUCENE, Resolution.MILLISECOND).equalsIgnoreCase(from)) {
					try {
						setSearchForCreationDateFrom(DateUtils.getDD_MM_YYYY(DateTools.stringToDate(from)));
					} catch (ParseException e) {
						setSearchForCreationDateFrom("");
					}
				} else {
					setSearchForCreationDateFrom("");
				}
				
				if (!DateTools.dateToString(DateUtils.MAX_DATE_FOR_LUCENE, Resolution.MILLISECOND).equalsIgnoreCase(until)) {
					try {
						setSearchForCreationDateUntil(DateUtils.getDD_MM_YYYY(DateTools.stringToDate(until)));
					} catch (ParseException e) {
						setSearchForCreationDateUntil("");
					}
				} else {
					setSearchForCreationDateUntil("");
				}
			} else {
				setSearchForCreationDateFrom("");
				setSearchForCreationDateUntil("");
			}
		} else {
			setSearchForCreationDateFrom("");
			setSearchForCreationDateUntil("");
		}
		
		setSearchForDynaAttributeNames(VKCStringUtils.filterUnicodeChars(values[2]));
		setSearchForDynaAttributeValues(VKCStringUtils.filterUnicodeChars(values[3]));
		setSearchForAuthor(VKCStringUtils.filterUnicodeChars(values[4]));
		setSearchForPublisher(VKCStringUtils.filterUnicodeChars(values[5]));
		setSearchForTitle(VKCStringUtils.filterUnicodeChars(values[6]));
		setSearchForKeywords(VKCStringUtils.filterUnicodeChars(values[7]));
		setSearchForDescription(VKCStringUtils.filterUnicodeChars(values[8]));
		setSearchForFilename(VKCStringUtils.filterUnicodeChars(values[9]));
		
		if ("".equals(values[10])) {
			setSelectedDocClassId("-1");
		} else if ("*".equals(values[10])) {
			setSelectedDocClassId(values[10]);
		} else {
			setSelectedDocClassId(StringUtils.decodeToInteger(values[10]).toString());
		}
		
		if ("".equals(values[11])) {
			setSelectedDocStatusId("-1");
		} else if ("*".equals(values[11])) {
			setSelectedDocStatusId(values[11]);
		} else {
			setSelectedDocStatusId(StringUtils.decodeToInteger(values[11]).toString());
		}
		
		List addAttributes = new ArrayList();
		
		try {
			addAttributes = new ArrayList(VKCAddAttributeSerializer.getAllAddDocAttributes());
		} catch (DBException e) {
			addAttributes = new ArrayList();
		}
		
		if (!addAttributes.isEmpty()) {
			for (int i = 0; i < addAttributes.size(); i++) {
				VKCAddAttribute addAttr = (VKCAddAttribute)addAttributes.get(i);
				String field = "adddocattrId_" + addAttr.getAttrId() + ":(";
				int startIndex = searchQuery.indexOf(field);
				int endIndex = searchQuery.indexOf(separator);
				
				if (startIndex != -1) {
					int index1 = startIndex + field.length();
					String value = searchQuery.substring(index1);
					int index2 = value.indexOf(tagEnd + separator);
					int endLength = tagEnd.length() + separator.length();
					
					if (index2 == -1) {
						index2 = value.indexOf(tagEnd);
						endLength = tagEnd.length();
					}
					
					value = value.substring(0, index2);
					endIndex = index1 + value.length() + endLength;
					setAddDocAttrValue("adddocattrId_" + addAttr.getAttrId(), VKCStringUtils.filterUnicodeChars(value));
					searchQuery = cutOut(searchQuery, startIndex, endIndex);
				}
			}
		}
		
		setSearchInAnyField(VKCStringUtils.filterUnicodeChars(StringUtils.normalize(searchQuery)));
	}

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

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

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

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

	private String cutOut(String str, int start, int end) {
		if (str == null || str.length() < 1 || start < 0 || end < 0 || start >= end) {
			return str;
		}
		
		String left = new String(str.substring(0, start));
		String right = new String(str.substring(end, str.length()));
		
		return new String(left + right);
	}

	public boolean isEmpty() {
		if (StringUtils.isEmpty(getSearchQuery())) {
			return true;
		} 

		return false;
	}
    
	public Integer getQueryId() {
        return queryId;
    }
    
    public void setQueryId(Integer i) {
        queryId = i;
    }

    public void setUserId(Integer i) {
        userId = i;
    }
    
    public Integer getUserId(){
        return userId;
    }

	public String getAttributeKeyName(String key) throws DBException {
	    if (!StringUtils.isEmpty(key)) {
	        if (getAllAddDocAttributes().containsKey(key)) {
	            return ((VKCAddAttribute)getAllAddDocAttributes().get(key)).getName();
	        }
	    }
	    
	    return key;
	}

    public String getSubjectForNotification() {
        return subjectForNotification;
    }

    public void setSubjectForNotification(String subjectForNotification) {
        this.subjectForNotification = subjectForNotification;
    }
}