Package ch.entwine.weblounge.common.impl.content

Source Code of ch.entwine.weblounge.common.impl.content.SearchQueryImpl

/*
*  Weblounge: Web Content Management System
*  Copyright (c) 2003 - 2011 The Weblounge Team
*  http://entwinemedia.com/weblounge
*
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public License
*  as published by the Free Software Foundation; either version 2
*  of the License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public License
*  along with this program; if not, write to the Free Software Foundation
*  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package ch.entwine.weblounge.common.impl.content;

import static ch.entwine.weblounge.common.content.SearchQuery.Quantifier.Any;

import ch.entwine.weblounge.common.content.Resource;
import ch.entwine.weblounge.common.content.SearchQuery;
import ch.entwine.weblounge.common.content.SearchTerms;
import ch.entwine.weblounge.common.content.page.Pagelet;
import ch.entwine.weblounge.common.content.page.PageletURI;
import ch.entwine.weblounge.common.impl.content.page.PageletImpl;
import ch.entwine.weblounge.common.impl.content.page.PageletURIImpl;
import ch.entwine.weblounge.common.impl.security.UserImpl;
import ch.entwine.weblounge.common.language.Language;
import ch.entwine.weblounge.common.security.User;
import ch.entwine.weblounge.common.site.Site;
import ch.entwine.weblounge.common.url.UrlUtils;
import ch.entwine.weblounge.common.url.WebUrl;

import org.apache.commons.lang.StringUtils;

import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

/**
* Default implementation for the search query api.
*/
public class SearchQueryImpl implements SearchQuery {

  /** Name of the stage composer */
  public static final String STAGE_COMPOSER = "#stage#";

  /** Id of the wild card user */
  public static final String ANY_USER = "#any#";

  /** The list of fields to return */
  protected List<String> fields = null;

  /** The site */
  protected Site site = null;

  /** The search language */
  protected Language language = null;

  /** Query configuration stack */
  protected Stack<Object> stack = new Stack<Object>();

  /** The object that needs to show up next */
  protected Class<?> expectation = null;

  /** The resource identifier */
  protected List<String> resourceId = new ArrayList<String>();

  /** The path */
  protected String path = null;

  /** The types */
  protected List<String> types = new ArrayList<String>();

  /** The types to block */
  protected List<String> withoutTypes = new ArrayList<String>();

  /** The template */
  protected String template = null;

  /** The layout */
  protected String layout = null;

  /** Stationary flag */
  protected boolean stationary = false;

  /** The list of required pagelets */
  protected List<SearchTerms<Pagelet>> pagelets = null;

  /** The list of required subjects */
  protected List<SearchTerms<String>> subjects = null;

  /** The list of required series */
  protected List<String> series = new ArrayList<String>();

  /** The external location */
  protected URL externalLocation = null;

  /** The source */
  protected String source = null;

  /** The properties */
  protected Map<String, String> properties = new HashMap<String, String>();

  /** The elements */
  protected Map<String, String> elements = new HashMap<String, String>();

  /** The last method called */
  protected String lastMethod = null;

  /** The creation date */
  protected Date creationDateFrom = null;

  /** The end of the range for the creation date */
  protected Date creationDateTo = null;

  /** True if the resource must not have a modification date */
  protected boolean withoutModification = false;

  /** The modification date */
  protected Date modificationDateFrom = null;

  /** The end of the range for the modification date */
  protected Date modificationDateTo = null;

  /** True if the resource must not have a publishing date */
  protected boolean withoutPublication = false;

  /** The publishing date */
  protected Date publishingDateFrom = null;

  /** The end of the range for the publishing date */
  protected Date publishingDateTo = null;

  /** The author */
  protected User author = null;

  /** The creator */
  protected User creator = null;

  /** The modifier */
  protected User modifier = null;

  /** The publisher */
  protected User publisher = null;

  /** The lock owner */
  protected User lockOwner = null;

  /** The path prefix */
  protected String pathPrefix = null;

  /** The filename */
  protected String filename = null;

  /** The mime type */
  protected String mimetype = null;

  /** Fulltext query terms */
  protected List<SearchTerms<String>> fulltext = null;

  /** Query terms */
  protected List<SearchTerms<String>> text = null;

  /** True if the search text should be matched using wildcards */
  protected boolean fuzzySearch = true;

  /** Filter terms */
  protected String filter = null;

  /** The query offset */
  protected int offset = -1;

  /** The query limit */
  protected int limit = -1;

  /** True to boost more recent documents */
  protected boolean recencyBoost = false;

  /** Creation date order relation */
  protected Order creationDateSearchOrder = Order.None;

  /** Modification date order relation */
  protected Order modificationDateSearchOrder = Order.None;

  /** Publication date order relation */
  protected Order publicationDateSearchOrder = Order.None;

  /** The resource versions */
  protected long version = Resource.ANY;

  /** The preferred resource version */
  protected long preferredVersion = -1L;

  /**
   * Creates a new search query that is operating on the given site.
   *
   * @param site
   *          the site
   */
  public SearchQueryImpl(Site site) {
    this(site, site.getDefaultLanguage());
  }

  /**
   * Creates a new search query that is operating on the given site.
   *
   * @param site
   *          the site
   * @param language
   *          the search language
   */
  public SearchQueryImpl(Site site, Language language) {
    this.site = site;
    this.language = language;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withField(java.lang.String)
   */
  @Override
  public SearchQuery withField(String field) {
    if (fields == null)
      fields = new ArrayList<String>();
    fields.add(field);
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withFields(java.lang.String[])
   */
  @Override
  public SearchQuery withFields(String... fields) {
    for (String field : fields) {
      withField(field);
    }
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getFields()
   */
  @Override
  public String[] getFields() {
    if (fields == null)
      return new String[] {};
    return fields.toArray(new String[fields.size()]);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getSite()
   */
  public Site getSite() {
    return site;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withRececyPriority()
   */
  @Override
  public SearchQuery withRececyPriority() {
    this.recencyBoost = true;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getRecencyPriority()
   */
  @Override
  public boolean getRecencyPriority() {
    return recencyBoost;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withLimit(int)
   */
  public SearchQuery withLimit(int limit) {
    this.limit = limit;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getLimit()
   */
  public int getLimit() {
    return limit;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withOffset(int)
   */
  public SearchQuery withOffset(int offset) {
    this.offset = Math.max(0, offset);
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getOffset()
   */
  public int getOffset() {
    return offset;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withIdentifier(java.lang.String)
   */
  public SearchQuery withIdentifier(String id) {
    if (StringUtils.isBlank(id))
      throw new IllegalArgumentException("Id cannot be null");
    this.resourceId.add(id);
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getIdentifier()
   */
  public String[] getIdentifier() {
    return resourceId.toArray(new String[resourceId.size()]);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withPath(java.lang.String)
   */
  public SearchQuery withPath(String path) {
    if (path == null)
      throw new IllegalArgumentException("Path cannot be null");
    this.path = UrlUtils.trim(path);
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getPath()
   */
  public String getPath() {
    return path;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withTemplate(java.lang.String)
   */
  public SearchQuery withTemplate(String template) {
    this.template = template;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getTemplate()
   */
  public String getTemplate() {
    return template;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withLayout(java.lang.String)
   */
  public SearchQuery withLayout(String layout) {
    this.layout = layout;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getLayout()
   */
  public String getLayout() {
    return layout;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withStationary()
   */
  public SearchQuery withStationary() {
    stationary = true;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#isStationary()
   */
  public boolean isStationary() {
    return stationary;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withTypes(java.lang.String)
   */
  public SearchQuery withTypes(String... types) {
    for (String type : types) {
      this.types.add(type);
    }
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withoutTypes(java.lang.String)
   */
  public SearchQuery withoutTypes(String... types) {
    for (String type : types) {
      this.withoutTypes.add(type);
    }
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getType()
   */
  public String[] getTypes() {
    return types.toArray(new String[types.size()]);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getWithoutTypes()
   */
  public String[] getWithoutTypes() {
    return withoutTypes.toArray(new String[withoutTypes.size()]);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#and(java.util.Date)
   */
  public SearchQuery and(Date date) {
    ensureExpectation(Date.class);
    Date startDate = (Date) stack.peek();
    if (startDate.equals(date) || startDate.after(date))
      throw new IllegalStateException("End date must be after start date");
    if ("withCreationDateBetween".equals(lastMethod))
      creationDateTo = date;
    else if ("withModificationDateBetween".equals(lastMethod))
      modificationDateTo = date;
    else if ("withPublishingDateBetween".equals(lastMethod))
      publishingDateTo = date;
    clearExpectations();
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#andProperty(java.lang.String,
   *      java.lang.String)
   */
  public SearchQuery andProperty(String propertyName, String propertyValue)
      throws IllegalStateException {
    ensureConfigurationArray(Pagelet.class);
    Pagelet[] pagelets = (Pagelet[]) stack.peek();
    for (Pagelet pagelet : pagelets) {
      pagelet.addProperty(propertyName, propertyValue);
    }
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#andElement(java.lang.String,
   *      java.lang.String)
   */
  public SearchQuery andElement(String textName, String text)
      throws IllegalStateException {
    if (language == null)
      throw new IllegalStateException("You need to specify the query language first");
    ensureConfigurationArray(Pagelet.class);
    Pagelet[] pagelets = (Pagelet[]) stack.peek();
    for (Pagelet pagelet : pagelets) {
      pagelet.setContent(textName, text, language);
    }
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#atPosition(int)
   */
  public SearchQuery atPosition(int position) throws IllegalStateException {
    ensureConfigurationArray(Pagelet.class);
    Pagelet[] pagelets = (Pagelet[]) stack.peek();
    for (Pagelet pagelet : pagelets) {
      PageletURI uri = pagelet.getURI();
      if (uri == null) {
        uri = new PageletURIImpl(null, null, position);
      } else {
        uri.setPosition(position);
      }
      pagelet.setURI(uri);
    }
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#inComposer(java.lang.String)
   */
  public SearchQuery inComposer(String composer) throws IllegalStateException {
    ensureConfigurationArray(Pagelet.class);
    Pagelet[] pagelets = (Pagelet[]) stack.peek();
    for (Pagelet pagelet : pagelets) {
      PageletURI uri = pagelet.getURI();
      if (uri == null) {
        uri = new PageletURIImpl(null, composer, -1);
      } else {
        uri.setComposer(composer);
      }
      pagelet.setURI(uri);
    }
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#inStage()
   */
  public SearchQuery inStage() throws IllegalStateException {
    return inComposer(STAGE_COMPOSER);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withAuthor(ch.entwine.weblounge.common.security.User)
   */
  public SearchQuery withAuthor(User author) {
    clearExpectations();
    this.author = author;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getAuthor()
   */
  public User getAuthor() {
    return author;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withLanguage(ch.entwine.weblounge.common.language.Language)
   */
  public SearchQuery withLanguage(Language language) {
    clearExpectations();
    this.language = language;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getLanguage()
   */
  public Language getLanguage() {
    return language;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withSubject(java.lang.String)
   */
  public SearchQuery withSubject(String subject) {
    return withSubjects(Any, subject);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withSubjects(ch.entwine.weblounge.common.content.SearchQuery.Quantifier,
   *      String...)
   */
  @Override
  public SearchQuery withSubjects(Quantifier quantifier, String... subjects) {
    if (quantifier == null)
      throw new IllegalArgumentException("Quantifier must not be null");
    if (subjects == null)
      throw new IllegalArgumentException("Subjects must not be null");

    // Make sure the collection is initialized
    if (this.subjects == null)
      this.subjects = new ArrayList<SearchTerms<String>>();

    // Add the text to the search terms
    clearExpectations();
    with(this.subjects, quantifier, subjects);
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getSubjects()
   */
  public Collection<SearchTerms<String>> getSubjects() {
    return subjects;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withCreationDate(java.util.Date)
   */
  public SearchQuery withCreationDate(Date date) {
    clearExpectations();
    creationDateFrom = date;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withCreationDateBetween(java.util.Date)
   */
  public SearchQuery withCreationDateBetween(Date date) {
    clearExpectations();
    configure(date);
    creationDateFrom = date;
    expect(Date.class);
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getCreationDate()
   */
  public Date getCreationDate() {
    return creationDateFrom;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getCreationDateEnd()
   */
  public Date getCreationDateEnd() {
    return creationDateTo;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withModificationDate(java.util.Date)
   */
  public SearchQuery withModificationDate(Date date) {
    if (withoutModification)
      throw new IllegalStateException("With modification date and without modification date are mutually exclusive");
    clearExpectations();
    modificationDateFrom = date;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withModificationDateBetween(java.util.Date)
   */
  public SearchQuery withModificationDateBetween(Date date) {
    if (withoutModification)
      throw new IllegalStateException("With modification date and without modification date are mutually exclusive");
    clearExpectations();
    configure(date);
    modificationDateFrom = date;
    expect(Date.class);
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getModificationDate()
   */
  public Date getModificationDate() {
    return modificationDateFrom;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getModificationDateEnd()
   */
  public Date getModificationDateEnd() {
    return modificationDateTo;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withoutModification()
   */
  public SearchQuery withoutModification() {
    if (modificationDateFrom != null || modificationDateTo != null)
      throw new IllegalStateException("With modification date and without modification date are mutually exclusive");
    if (modifier != null)
      throw new IllegalStateException("With modifier and without modification date are mutually exclusive");
    clearExpectations();
    this.withoutModification = true;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getWithoutModification()
   */
  public boolean getWithoutModification() {
    return withoutModification;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withPagelet(ch.entwine.weblounge.common.content.page.Pagelet)
   */
  public SearchQuery withPagelet(Pagelet pagelet) {
    return withPagelets(Any, pagelet);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withPagelets(ch.entwine.weblounge.common.content.SearchQuery.Quantifier,
   *      ch.entwine.weblounge.common.content.page.Pagelet[])
   */
  @Override
  public SearchQuery withPagelets(Quantifier quantifier, Pagelet... pagelets) {
    if (pagelets == null)
      throw new IllegalArgumentException("Pagelet must not be null");
    if (quantifier == null)
      throw new IllegalArgumentException("Quantifier must not be null");

    // Make sure the collection is initialized
    if (this.pagelets == null)
      this.pagelets = new ArrayList<SearchTerms<Pagelet>>();

    int i = 0;
    for (Pagelet p : pagelets) {
      pagelets[i++] = new PageletImpl(p.getModule(), p.getIdentifier());
    }

    clearExpectations();
    with(this.pagelets, quantifier, pagelets);
    configure(pagelets);
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getPagelets()
   */
  public Collection<SearchTerms<Pagelet>> getPagelets() {
    return pagelets;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withPathPrefix(java.lang.String)
   */
  public SearchQuery withPathPrefix(String path) {
    clearExpectations();
    if (path.endsWith("/"))
      path = path.substring(0, path.length() - 1);
    this.pathPrefix = path;
    if (pathPrefix == null)
      throw new IllegalArgumentException("Path prefix must not be null");
    if (!pathPrefix.startsWith(WebUrl.separator))
      pathPrefix = WebUrl.separatorChar + pathPrefix;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getPathPrefix()
   */
  public String getPathPrefix() {
    return pathPrefix;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withCreator(ch.entwine.weblounge.common.security.User)
   */
  public SearchQuery withCreator(User creator) {
    clearExpectations();
    this.creator = creator;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getCreator()
   */
  public User getCreator() {
    return creator;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withModifier(ch.entwine.weblounge.common.security.User)
   */
  public SearchQuery withModifier(User modifier) {
    if (withoutModification)
      throw new IllegalStateException("With modifier and without modification date are mutually exclusive");
    clearExpectations();
    this.modifier = modifier;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getModifier()
   */
  public User getModifier() {
    return modifier;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withPublisher(ch.entwine.weblounge.common.security.User)
   */
  public SearchQuery withPublisher(User publisher) {
    if (withoutPublication)
      throw new IllegalStateException("With publisher and without publication date are mutually exclusive");
    clearExpectations();
    this.publisher = publisher;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getPublisher()
   */
  public User getPublisher() {
    return publisher;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withPublishingDate(java.util.Date)
   */
  public SearchQuery withPublishingDate(Date date) {
    if (withoutPublication)
      throw new IllegalStateException("With publishing date and without publication are mutually exclusive");
    clearExpectations();
    this.publishingDateFrom = date;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withPublishingDateBetween(java.util.Date)
   */
  public SearchQuery withPublishingDateBetween(Date date) {
    if (withoutPublication)
      throw new IllegalStateException("With publishing date and without publication are mutually exclusive");
    clearExpectations();
    configure(date);
    this.publishingDateFrom = date;
    expect(Date.class);
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getPublishingDate()
   */
  public Date getPublishingDate() {
    return publishingDateFrom;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getPublishingDateEnd()
   */
  public Date getPublishingDateEnd() {
    return publishingDateTo;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withoutPublication()
   */
  public SearchQuery withoutPublication() {
    if (publishingDateFrom != null || publishingDateTo != null)
      throw new IllegalStateException("With publishing date and without publishing date are mutually exclusive");
    if (publisher != null)
      throw new IllegalStateException("With publisher and without modification date are mutually exclusive");
    clearExpectations();
    this.withoutPublication = true;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getWithoutPublication()
   */
  public boolean getWithoutPublication() {
    return withoutPublication;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withLockOwner()
   */
  public SearchQuery withLockOwner() {
    clearExpectations();
    this.lockOwner = new UserImpl(ANY_USER);
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withLockOwner(ch.entwine.weblounge.common.security.User)
   */
  public SearchQuery withLockOwner(User lockOwner) {
    clearExpectations();
    this.lockOwner = lockOwner;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getLockOwner()
   */
  public User getLockOwner() {
    return lockOwner;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withExternalLocation(java.net.URL)
   */
  public SearchQuery withExternalLocation(URL url) {
    this.externalLocation = url;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getExternalLocation()
   */
  public URL getExternalLocation() {
    return externalLocation;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withText(java.lang.String)
   */
  public SearchQuery withText(String text) {
    return withText(false, Any, text);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withText(boolean,
   *      java.lang.String)
   */
  public SearchQuery withText(boolean wildcardSearch, String text) {
    return withText(wildcardSearch, Any, text);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withText(boolean,
   *      ch.entwine.weblounge.common.content.SearchQuery.Quantifier,
   *      java.lang.String[])
   */
  @Override
  public SearchQuery withText(boolean wildcardSearch, Quantifier quantifier,
      String... text) {
    if (quantifier == null)
      throw new IllegalArgumentException("Quantifier must not be null");
    if (text == null)
      throw new IllegalArgumentException("Text must not be null");

    // Make sure the collection is initialized
    if (this.text == null)
      this.text = new ArrayList<SearchTerms<String>>();

    // Add the text to the search terms
    clearExpectations();
    this.fuzzySearch = wildcardSearch;
    with(this.text, quantifier, text);
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getTerms()
   */
  public Collection<SearchTerms<String>> getTerms() {
    if (text == null)
      return Collections.emptyList();
    return text;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getQueryString()
   */
  @Override
  public String getQueryString() {
    if (text == null)
      return null;
    StringBuffer query = new StringBuffer();
    for (SearchTerms<String> s : text) {
      for (String t : s.getTerms()) {
        if (query.length() == 0)
          query.append(" ");
        query.append(t);
      }
    }
    return query.toString();
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withFulltext(java.lang.String)
   */
  @Override
  public SearchQuery withFulltext(String text) {
    return withFulltext(false, Any, text);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withFulltext(boolean,
   *      java.lang.String)
   */
  @Override
  public SearchQuery withFulltext(boolean fuzzy, String text) {
    return withFulltext(fuzzy, Any, text);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withFulltext(boolean,
   *      ch.entwine.weblounge.common.content.SearchQuery.Quantifier,
   *      java.lang.String[])
   */
  public SearchQuery withFulltext(boolean fuzzy, Quantifier quantifier,
      String... text) {
    if (quantifier == null)
      throw new IllegalArgumentException("Quantifier must not be null");
    if (text == null)
      throw new IllegalArgumentException("Text must not be null");

    // Make sure the collection is initialized
    if (this.fulltext == null)
      this.fulltext = new ArrayList<SearchTerms<String>>();

    // Add the text to the search terms
    clearExpectations();
    this.fuzzySearch = fuzzy;
    with(this.fulltext, quantifier, text);
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getFulltext()
   */
  @Override
  public Collection<SearchTerms<String>> getFulltext() {
    return fulltext;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#isFuzzySearch()
   */
  public boolean isFuzzySearch() {
    return fuzzySearch;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withFilter(java.lang.String)
   */
  public SearchQuery withFilter(String filter) {
    clearExpectations();
    this.filter = filter;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getFilter()
   */
  public String getFilter() {
    return filter;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withElement(java.lang.String,
   *      java.lang.String)
   */
  public SearchQuery withElement(String element, String value) {
    elements.put(element, value);
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getElements()
   */
  public Map<String, String> getElements() {
    return elements;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withProperty(java.lang.String,
   *      java.lang.String)
   */
  public SearchQuery withProperty(String property, String value) {
    properties.put(property, value);
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getProperties()
   */
  public Map<String, String> getProperties() {
    return properties;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withFilename(java.lang.String)
   */
  public SearchQuery withFilename(String filename) {
    this.filename = filename;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getFilename()
   */
  public String getFilename() {
    return filename;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withMimetype(java.lang.String)
   */
  public SearchQuery withMimetype(String mimetype) {
    this.mimetype = mimetype;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getMimetype()
   */
  public String getMimetype() {
    return mimetype;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#sortByCreationDate(ch.entwine.weblounge.common.content.SearchQuery.Order)
   */
  public SearchQuery sortByCreationDate(Order order) {
    if (order == null)
      creationDateSearchOrder = Order.None;
    else
      creationDateSearchOrder = order;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getCreationDateSortOrder()
   */
  public Order getCreationDateSortOrder() {
    return creationDateSearchOrder;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#sortByModificationDate(ch.entwine.weblounge.common.content.SearchQuery.Order)
   */
  public SearchQuery sortByModificationDate(Order order) {
    if (order == null)
      modificationDateSearchOrder = Order.None;
    else
      modificationDateSearchOrder = order;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getModificationDateSortOrder()
   */
  public Order getModificationDateSortOrder() {
    return modificationDateSearchOrder;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#sortByPublishingDate(ch.entwine.weblounge.common.content.SearchQuery.Order)
   */
  public SearchQuery sortByPublishingDate(Order order) {
    if (order == null)
      publicationDateSearchOrder = Order.None;
    else
      publicationDateSearchOrder = order;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getPublishingDateSortOrder()
   */
  public Order getPublishingDateSortOrder() {
    return publicationDateSearchOrder;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withVersion(long)
   */
  public SearchQuery withVersion(long version) {
    this.version = version;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withPreferredVersion(long)
   */
  public SearchQuery withPreferredVersion(long preferredVersion) {
    this.preferredVersion = preferredVersion;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getVersion()
   */
  public long getVersion() {
    return version;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getPreferredVersion()
   */
  public long getPreferredVersion() {
    return preferredVersion;
  }

  /**
   * Pushes the configuration object onto the stack.
   *
   * @param object
   *          the object
   */
  private void configure(Object object) {
    stack.push(object);
  }

  /**
   * Sets the expectation to <code>c</code>, making sure that the next
   * configuration object will either match <code>c</code> in terms of class of
   * throw an <code>IllegalStateException</code> if it doesn't.
   *
   * @param c
   *          the class type
   */
  private void expect(Class<?> c) {
    lastMethod = Thread.currentThread().getStackTrace()[2].getMethodName();
    this.expectation = c;
  }

  /**
   * This method is called if nothing should be expected by anyone. If this is
   * not the case (e. g. some unfinished query configuration is still in place)
   * we throw an <code>IllegalStateException</code>.
   *
   * @throws IllegalStateException
   *           if some object is expected
   */
  private void clearExpectations() throws IllegalStateException {
    if (expectation != null)
      throw new IllegalStateException("Query configuration expects " + expectation.getClass().getName());
    stack.clear();
  }

  /**
   * This method is called if a certain type of object is expected by someone.
   * If this is not the case (e. g. query configuration is in good shape, then
   * someone tries to "finish" a configuration part) we throw an
   * <code>IllegalStateException</code>.
   *
   * @throws IllegalStateException
   *           if no or a different object is expected
   */
  private void ensureExpectation(Class<?> c) throws IllegalStateException {
    if (expectation == null)
      throw new IllegalStateException("Malformed query configuration. No " + c.getClass().getName() + " is expected at this time");
    if (!expectation.getCanonicalName().equals(c.getCanonicalName()))
      throw new IllegalStateException("Malformed query configuration. Something of type " + c.getClass().getName() + " is expected at this time");
    expectation = null;
  }

  /**
   * Make sure that an object of type <code>c</code> is on the stack, throw an
   * <code>IllegalStateException</code> otherwise.
   *
   * @throws IllegalStateException
   *           if no object of type <code>c</code> was found on the stack
   */
  protected void ensureConfigurationObject(Class<?> c)
      throws IllegalStateException {
    for (Object o : stack) {
      if (c.isAssignableFrom(o.getClass()))
        return;
    }
    throw new IllegalStateException("Malformed query configuration. No " + c.getClass().getName() + " is expected at this time");
  }

  /**
   * Make sure that an array of type <code>c</code> is on the stack, throw an
   * <code>IllegalStateException</code> otherwise.
   *
   * @throws IllegalStateException
   *           if no array of type <code>c</code> was found on the stack
   */
  protected void ensureConfigurationArray(Class<?> c)
      throws IllegalStateException {
    for (Object o : stack) {
      if (o.getClass().isArray() && c.isAssignableFrom(o.getClass().getComponentType()))
        return;
    }
    throw new IllegalStateException("Malformed query configuration. No " + c.getClass().getName() + " is expected at this time");
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withSource(java.lang.String)
   */
  public SearchQuery withSource(String source) {
    this.source = source;
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getSource()
   */
  public String getSource() {
    return source;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#withSeries(java.lang.String)
   */
  public SearchQuery withSeries(String series) {
    this.series.add(series);
    return this;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.content.SearchQuery#getSeries()
   */
  public String[] getSeries() {
    return series.toArray(new String[series.size()]);
  }

  /**
   * Utility method to add the given values to the list of search terms using
   * the specified quantifier.
   *
   * @param searchTerms
   *          the terms
   * @param quantifier
   *          the quantifier
   * @param values
   *          the values
   * @return the extended search terms
   */
  private <T extends Object> SearchTerms<T> with(
      List<SearchTerms<T>> searchTerms, Quantifier quantifier, T... values) {
    SearchTerms<T> terms = null;

    // Handle any quantifier
    if (values.length == 1 || Any.equals(quantifier)) {

      // Check if there is a default terms collection
      for (SearchTerms<T> t : searchTerms) {
        if (Quantifier.Any.equals(t.getQuantifier())) {
          terms = t;
          break;
        }
      }

      // Has there been a default terms collection?
      if (terms == null) {
        terms = new SearchTermsImpl<T>(Quantifier.Any, values);
        searchTerms.add(terms);
      }

      // Add the text
      for (T v : values) {
        terms.add(v);
      }
    }

    // All quantifier
    else {
      terms = new SearchTermsImpl<T>(quantifier, values);
      searchTerms.add(terms);
    }

    return terms;
  }

}
TOP

Related Classes of ch.entwine.weblounge.common.impl.content.SearchQueryImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.