/*
 * Copyright 2016 Jaakko Hannikainen
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package fi.jgke.tagger.controller;

import fi.jgke.tagger.domain.Source;
import fi.jgke.tagger.repository.SourceRepository;
import fi.jgke.tagger.domain.Tag;
import fi.jgke.tagger.repository.TagRepository;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
@RequestMapping("/search")
public class TagSearchController {

    @Autowired
    SourceRepository sourceRepository;

    @Autowired
    TagRepository tagRepository;

    @RequestMapping
    public String getSource(Model model, @RequestParam String tagstring) {
        List<String> strings = Arrays.asList(tagstring.split(" "));
        Stream<String> tagstrings = strings.stream()
                .filter((t) -> !t.startsWith("!"));
        Stream<String> nottagstrings = strings.stream()
                .filter((t) -> t.startsWith("!"))
                .map((t) -> t.substring(1));
        Set<Tag> tags = tagstrings
                .map((t) -> tagRepository.findByValue(t))
                .filter((t) -> t != null)
                .collect(Collectors.toSet());
        Set<Tag> nottags = nottagstrings
                .map((t) -> tagRepository.findByValue(t))
                .filter((t) -> t != null)
                .collect(Collectors.toSet());
        Set<Source> filtered_sources = tags.stream()
                .map((t) -> t.getSources())
                .flatMap(Collection::stream)
                .filter((s) -> s.getTags().stream()
                        .allMatch((t) -> !nottags.contains(t)))
                .filter((s) -> s.getTags().containsAll(tags))
                .collect(Collectors.toSet());
        model.addAttribute("searchquery", tagstring);
        model.addAttribute("sources", new ArrayList<>(filtered_sources));
        return "tagsearch";
    }

}

@@ -1486,95 +1486,60 @@
     
-@RequestMapping%0A    public String getSource(Model model, @RequestParam 
+private Set%3CTag%3E getTagsFromList(Stream%3C
 String
+%3E
  tags
-tring
 ) %7B%0A
@@ -1550,177 +1550,170 @@
     
-List%3CString%3E strings = Arrays.asList(tagstring.split(%22 %22));%0A        Stream%3CString%3E tagstrings = strings.stream()%0A                .filter((t) -%3E !t.startsWith(%22!%22
+return tags%0A                .map((t) -%3E tagRepository.findByValue(t))%0A                .filter((t) -%3E t != null)%0A                .collect(Collectors.toSet(
 ));%0A    
     
@@ -1712,108 +1712,171 @@
     
+%7D%0A%0A
     
-Stream%3CString%3E nottagstrings = strings.stream()%0A                .filter((t) -%3E t.startsWith(%22!%22)
+private Set%3CSource%3E getSourcesFromTags(Set%3CTag%3E tags, Set%3CTag%3E nottags) %7B%0A        return tags.stream()%0A                .findAny().get().getSources().stream(
 )%0A  
@@ -1894,128 +1894,106 @@
    .
-map((t
+filter((s
 ) -%3E 
-t.substring(1));%0A        Set%3CTag%3E tags = tagstrings%0A                .map((t) -%3E tagRepository.findByValue
+s.getTags().stream()%0A                        .allMatch((t) -%3E !nottags.contains
 (t))
+)
 %0A   
@@ -2010,39 +2010,59 @@
    .filter((
-t
+s
 ) -%3E 
-t != null
+s.getTags().containsAll(tags)
 )%0A          
@@ -2105,232 +2105,215 @@
     
+%7D%0A%0A
     
-Set%3CTag%3E nottags = nottagstrings%0A                .map((t) -%3E tagRepository.findByValue(t))%0A                .filter((t) -%3E t != null)%0A                .collect(Collectors.toSet());%0A        Set%3CSource%3E filtered_sources = ta
+@RequestMapping%0A    public String getSource(Model model, @RequestParam String tagstring) %7B%0A        List%3CString%3E strings = Arrays.asList(tagstring.split(%22 %22));%0A        Stream%3CString%3E tagstrings = strin
 gs.s
@@ -2337,27 +2337,30 @@
        .
-map
+filter
 ((t) -%3E 
 t.getSou
@@ -2355,23 +2355,28 @@
  -%3E 
+!
 t.
-getSources(
+startsWith(%22!%22
 ))
+;
 %0A   
@@ -2384,43 +2384,54 @@
     
-        .flatMap(Collection::
+Stream%3CString%3E nottagstrings = strings.
 stream
+(
 )%0A  
@@ -2457,207 +2457,266 @@
 er((
-s
+t
 ) -%3E 
-s.getTags().stream()%0A                        .allMatch((t) -%3E !nottags.contains(t)))%0A                .filter((s) -%3E s.getTags().containsAll(tags))%0A                .collect(Collectors.toSet()
+t.startsWith(%22!%22))%0A                .map((t) -%3E t.substring(1));%0A%0A        Set%3CTag%3E tags = getTagsFromList(tagstrings);%0A        Set%3CTag%3E nottags = getTagsFromList(nottagstrings);%0A        Set%3CSource%3E filtered_sources = getSourcesFromTags(tags, nottags
 );%0A
+%0A
     

Improve tag search code a bit