001/*
002 * flattr4j - A Java library for Flattr
003 *
004 * Copyright (C) 2012 Richard "Shred" Körber
005 *   http://flattr4j.shredzone.org
006 *
007 * This program is free software: you can redistribute it and/or modify
008 * it under the terms of the GNU General Public License / GNU Lesser
009 * General Public License as published by the Free Software Foundation,
010 * either version 3 of the License, or (at your option) any later version.
011 *
012 * Licensed under the Apache License, Version 2.0 (the "License");
013 * you may not use this file except in compliance with the License.
014 *
015 * This program is distributed in the hope that it will be useful,
016 * but WITHOUT ANY WARRANTY; without even the implied warranty of
017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
018 */
019package org.shredzone.flattr4j.model;
020
021import java.io.Serializable;
022import java.util.ArrayList;
023import java.util.Collection;
024
025import org.shredzone.flattr4j.connector.Connection;
026
027/**
028 * Collects search parameters. Every parameter is optional.
029 *
030 * @author Richard "Shred" Körber
031 * @since 2.0
032 */
033public class SearchQuery implements Serializable {
034    private static final long serialVersionUID = 8144711465654878363L;
035
036    /**
037     * Enumeration of available sort orders.
038     */
039    public static enum Order {
040        RELEVANCE, TREND, FLATTRS, FLATTRS_MONTH, FLATTRS_WEEK, FLATTRS_DAY;
041    }
042
043    private String query;
044    private String tags;
045    private String url;
046    private ArrayList<LanguageId> languageList = new ArrayList<LanguageId>();
047    private ArrayList<CategoryId> categoryList = new ArrayList<CategoryId>();
048    private String user;
049    private Order sort;
050
051    /**
052     * Text to search for.
053     */
054    public String getQuery()                    { return query; }
055    public void setQuery(String query)          { this.query = query; }
056
057    /**
058     * Tags to search for. Allows logical operators: '|' (or), '&amp;' (and), '!' (not).
059     * For example, "game | games ! software" means: search for "game" or "games", but not
060     * "software".
061     */
062    public String getTags()                     { return tags; }
063    public void setTags(String tags)            { this.tags = tags; }
064
065    /**
066     * URL to search for.
067     */
068    public String getUrl()                      { return url; }
069    public void setUrl(String url)              { this.url = url; }
070
071    /**
072     * Adds a language to search for.
073     * <p>
074     * If the collection has been changed via {@link #setLanguages(Collection)}, it
075     * must be modifiable.
076     *
077     * @since 2.5
078     */
079    public void addLanguage(LanguageId language) {
080        if (language != null) {
081            languageList.add(language);
082        }
083    }
084
085    /**
086     * Returns the collection of languages to search for. The default collection is
087     * modifiable.
088     *
089     * @since 2.5
090     */
091    public Collection<LanguageId> getLanguages() {
092        return languageList;
093    }
094
095    /**
096     * Sets a collection of languages to search for.
097     *
098     * @param languages
099     *            Collection of {@link LanguageId} to be used for searching. Must not be
100     *            {@code null}.
101     * @since 2.5
102     */
103    public void setLanguages(Collection<LanguageId> languages) {
104        if (languages == null) {
105            throw new IllegalArgumentException("languages list must not be null");
106        }
107        languageList = new ArrayList<LanguageId>(languages);
108    }
109
110    /**
111     * User to search for.
112     */
113    public UserId getUser()                     { return user != null ? User.withId(user) : null; }
114    public void setUser(UserId user)            { this.user = user.getUserId(); }
115
116    /**
117     * Sort order. Defaults to {@link Order#RELEVANCE}.
118     */
119    public Order getSort()                      { return sort; }
120    public void setSort(Order sort)             { this.sort = sort; }
121
122    /**
123     * Adds a category to search for.
124     * <p>
125     * If the collection has been changed via {@link #setCategories(Collection)}, it
126     * must be modifiable.
127     *
128     * @since 2.2
129     */
130    public void addCategory(CategoryId category) {
131        if (category != null) {
132            categoryList.add(category);
133        }
134    }
135
136    /**
137     * Returns the collection of categories to search for.
138     * <p>
139     * Since 2.5, the default collection is modifiable.
140     *
141     * @since 2.2
142     */
143    public Collection<CategoryId> getCategories() {
144        return categoryList;
145    }
146
147    /**
148     * Sets a collection of categories to search for.
149     *
150     * @param categories
151     *            Collection of {@link CategoryId} to be used for searching. Must not be
152     *            {@code null}.
153     * @since 2.5
154     */
155    public void setCategories(Collection<CategoryId> categories) {
156        if (categories == null) {
157            throw new IllegalArgumentException("categories list must not be null");
158        }
159        categoryList = new ArrayList<CategoryId>(categories);
160    }
161
162
163    /**
164     * Text to search for.
165     */
166    public SearchQuery query(String query) {
167        setQuery(query);
168        return this;
169    }
170
171    /**
172     * Sets a tag expression to search for.
173     */
174    public SearchQuery tags(String tags) {
175        setTags(tags);
176        return this;
177    }
178
179    /**
180     * Language to search for.
181     * <p>
182     * Since version 2.5, multiple languages can be set by invoking this call multiple
183     * times.
184     */
185    public SearchQuery language(LanguageId language) {
186        addLanguage(language);
187        return this;
188    }
189
190    /**
191     * Category to search for.
192     * <p>
193     * Since version 2.2, multiple categories can be set by invoking this call multiple
194     * times.
195     */
196    public SearchQuery category(CategoryId category) {
197        addCategory(category);
198        return this;
199    }
200
201    /**
202     * User to search for.
203     */
204    public SearchQuery user(UserId user) {
205        setUser(user);
206        return this;
207    }
208
209    /**
210     * Order to sort the result by.
211     */
212    public SearchQuery sort(Order order) {
213        setSort(order);
214        return this;
215    }
216
217    /**
218     * Sets up a {@link Connection} with the current search parameters.
219     *
220     * @param conn
221     *            {@link Connection} to set up
222     */
223    public void setupConnection(Connection conn) {
224        if (query != null) {
225            conn.query("query", query);
226        }
227
228        if (tags != null) {
229            conn.query("tags", tags);
230        }
231
232        if (url != null) {
233            conn.query("url", url);
234        }
235
236        if (!languageList.isEmpty()) {
237            StringBuilder sb = new StringBuilder();
238            for (LanguageId lid : languageList) {
239                sb.append(',').append(lid.getLanguageId());
240            }
241            if (sb.length() > 0) {
242                conn.query("language", sb.substring(1));
243            }
244        }
245
246        if (!categoryList.isEmpty()) {
247            StringBuilder sb = new StringBuilder();
248            for (CategoryId cid : categoryList) {
249                sb.append(',').append(cid.getCategoryId());
250            }
251            if (sb.length() > 0) {
252                conn.query("category", sb.substring(1));
253            }
254        }
255
256        if (user != null) {
257            conn.query("user", user);
258        }
259
260        if (sort != null) {
261            conn.query("sort", sort.name().toLowerCase());
262        }
263    }
264
265}