Allow user to configuration the number of posts shown on a page.
[Sone.git] / src / main / java / net / pterodactylus / sone / web / SearchPage.java
index bd0354f..1d1aa36 100644 (file)
@@ -65,6 +65,9 @@ public class SearchPage extends SoneTemplatePage {
        // SONETEMPLATEPAGE METHODS
        //
 
+       /**
+        * {@inheritDoc}
+        */
        @Override
        protected void processTemplate(Request request, TemplateContext templateContext) throws RedirectException {
                super.processTemplate(request, templateContext);
@@ -76,14 +79,14 @@ public class SearchPage extends SoneTemplatePage {
                List<Phrase> phrases = parseSearchPhrases(query);
 
                Set<Sone> sones = webInterface.getCore().getSones();
-               Set<Hit<Sone>> soneHits = getHits(sones, phrases, SoneStringGenerator.GENERATOR);
+               Set<Hit<Sone>> soneHits = getHits(sones, phrases, SoneStringGenerator.COMPLETE_GENERATOR);
 
                Set<Post> posts = new HashSet<Post>();
                for (Sone sone : sones) {
                        posts.addAll(sone.getPosts());
                }
                @SuppressWarnings("synthetic-access")
-               Set<Hit<Post>> postHits = getHits(posts, phrases, new PostStringGenerator());
+               Set<Hit<Post>> postHits = getHits(Filters.filteredSet(posts, Post.FUTURE_POSTS_FILTER), phrases, new PostStringGenerator());
 
                /* now filter. */
                soneHits = Filters.filteredSet(soneHits, Hit.POSITIVE_FILTER);
@@ -100,8 +103,8 @@ public class SearchPage extends SoneTemplatePage {
                List<Post> resultPosts = Converters.convertList(sortedPostHits, new HitConverter<Post>());
 
                /* pagination. */
-               Pagination<Sone> sonePagination = new Pagination<Sone>(resultSones, 10).setPage(Numbers.safeParseInteger(request.getHttpRequest().getParam("sonePage"), 0));
-               Pagination<Post> postPagination = new Pagination<Post>(resultPosts, 10).setPage(Numbers.safeParseInteger(request.getHttpRequest().getParam("postPage"), 0));
+               Pagination<Sone> sonePagination = new Pagination<Sone>(resultSones, webInterface.getCore().getPreferences().getPostsPerPage()).setPage(Numbers.safeParseInteger(request.getHttpRequest().getParam("sonePage"), 0));
+               Pagination<Post> postPagination = new Pagination<Post>(resultPosts, webInterface.getCore().getPreferences().getPostsPerPage()).setPage(Numbers.safeParseInteger(request.getHttpRequest().getParam("postPage"), 0));
 
                templateContext.set("sonePagination", sonePagination);
                templateContext.set("soneHits", sonePagination.getItems());
@@ -144,8 +147,8 @@ public class SearchPage extends SoneTemplatePage {
         * Parses the given query into search phrases. The query is split on
         * whitespace while allowing to group words using single or double quotes.
         * Isolated phrases starting with a “+” are
-        * {@link Phrase.Optionality#REQUIRED}, phrases with a
-        * “-” are {@link Phrase.Optionality#FORBIDDEN}.
+        * {@link Phrase.Optionality#REQUIRED}, phrases with a “-” are
+        * {@link Phrase.Optionality#FORBIDDEN}.
         *
         * @param query
         *            The query to parse
@@ -188,21 +191,31 @@ public class SearchPage extends SoneTemplatePage {
                int forbiddenHits = 0;
                int requiredPhrases = 0;
                for (Phrase phrase : phrases) {
+                       String phraseString = phrase.getPhrase().toLowerCase();
                        if (phrase.getOptionality() == Phrase.Optionality.REQUIRED) {
                                ++requiredPhrases;
                        }
-                       boolean matches = expression.toLowerCase().contains(phrase.getPhrase().toLowerCase());
-                       if (!matches) {
+                       int matches = 0;
+                       int index = 0;
+                       while (index < expression.length()) {
+                               int position = expression.toLowerCase().indexOf(phraseString, index);
+                               if (position == -1) {
+                                       break;
+                               }
+                               index = position + phraseString.length();
+                               ++matches;
+                       }
+                       if (matches == 0) {
                                continue;
                        }
                        if (phrase.getOptionality() == Phrase.Optionality.REQUIRED) {
-                               ++requiredHits;
+                               requiredHits += matches;
                        }
                        if (phrase.getOptionality() == Phrase.Optionality.OPTIONAL) {
-                               ++optionalHits;
+                               optionalHits += matches;
                        }
                        if (phrase.getOptionality() == Phrase.Optionality.FORBIDDEN) {
-                               ++forbiddenHits;
+                               forbiddenHits += matches;
                        }
                }
                return requiredHits * 3 + optionalHits + (requiredHits - requiredPhrases) * 5 - (forbiddenHits * 2);
@@ -236,8 +249,28 @@ public class SearchPage extends SoneTemplatePage {
         */
        private static class SoneStringGenerator implements StringGenerator<Sone> {
 
-               /** A static instance of the Sone string generator. */
-               public static final SoneStringGenerator GENERATOR = new SoneStringGenerator();
+               /** A static instance of a complete Sone string generator. */
+               public static final SoneStringGenerator COMPLETE_GENERATOR = new SoneStringGenerator(true);
+
+               /**
+                * A static instance of a Sone string generator that will only use the
+                * name of the Sone.
+                */
+               public static final SoneStringGenerator NAME_GENERATOR = new SoneStringGenerator(false);
+
+               /** Whether to generate a string from all data of a Sone. */
+               private final boolean complete;
+
+               /**
+                * Creates a new Sone string generator.
+                *
+                * @param complete
+                *            {@code true} to use the profile’s fields, {@code false} to
+                *            not to use the profile‘s fields
+                */
+               private SoneStringGenerator(boolean complete) {
+                       this.complete = complete;
+               }
 
                /**
                 * {@inheritDoc}
@@ -256,8 +289,10 @@ public class SearchPage extends SoneTemplatePage {
                        if (soneProfile.getLastName() != null) {
                                soneString.append(' ').append(soneProfile.getLastName());
                        }
-                       for (Field field : soneProfile.getFields()) {
-                               soneString.append(' ').append(field.getValue());
+                       if (complete) {
+                               for (Field field : soneProfile.getFields()) {
+                                       soneString.append(' ').append(field.getValue());
+                               }
                        }
                        return soneString.toString();
                }
@@ -267,8 +302,7 @@ public class SearchPage extends SoneTemplatePage {
        /**
         * Generates a {@link String} from a {@link Post}, concatenating the text of
         * the post, the text of all {@link Reply}s, and the name of all
-        * {@link Sone}s that have
-        * replied.
+        * {@link Sone}s that have replied.
         *
         * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
         */
@@ -282,10 +316,10 @@ public class SearchPage extends SoneTemplatePage {
                        StringBuilder postString = new StringBuilder();
                        postString.append(post.getText());
                        if (post.getRecipient() != null) {
-                               postString.append(' ').append(SoneStringGenerator.GENERATOR.generateString(post.getRecipient()));
+                               postString.append(' ').append(SoneStringGenerator.NAME_GENERATOR.generateString(post.getRecipient()));
                        }
-                       for (Reply reply : webInterface.getCore().getReplies(post)) {
-                               postString.append(' ').append(SoneStringGenerator.GENERATOR.generateString(reply.getSone()));
+                       for (Reply reply : Filters.filteredList(webInterface.getCore().getReplies(post), Reply.FUTURE_REPLIES_FILTER)) {
+                               postString.append(' ').append(SoneStringGenerator.NAME_GENERATOR.generateString(reply.getSone()));
                                postString.append(' ').append(reply.getText());
                        }
                        return postString.toString();
@@ -437,6 +471,9 @@ public class SearchPage extends SoneTemplatePage {
         */
        public static class HitConverter<T> implements Converter<Hit<T>, T> {
 
+               /**
+                * {@inheritDoc}
+                */
                @Override
                public T convert(Hit<T> input) {
                        return input.getObject();