Pattern combinator (#1105)

*  init

*  add pattern
This commit is contained in:
Boris
2019-11-26 06:03:04 +00:00
committed by Ilkka Seppälä
parent a9c3df78ee
commit 05e582ca3e
9 changed files with 556 additions and 27 deletions

View File

@ -0,0 +1,92 @@
/*
* The MIT License
* Copyright © 2014-2019 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.combinator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The functional pattern representing a style of organizing libraries
* centered around the idea of combining functions.
* Putting it simply, there is some type T, some functions
* for constructing "primitive" values of type T,
* and some "combinators" which can combine values of type T
* in various ways to build up more complex values of type T.
* The class {@link Finder} defines a simple function {@link Finder#find(String)}
* and connected functions
* {@link Finder#or(Finder)},
* {@link Finder#not(Finder)},
* {@link Finder#and(Finder)}
* Using them the became possible to get more complex functions {@link Finders}
*/
public class CombinatorApp {
/**
* Logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(CombinatorApp.class);
/**
* main.
* @param args args
*/
public static void main(String[] args) {
var queriesOr = new String[]{"many", "Annabel"};
var finder = Finders.expandedFinder(queriesOr);
var res = finder.find(text());
LOGGER.info("the result of expanded(or) query[{}] is {}", queriesOr, res);
var queriesAnd = new String[]{"Annabel", "my"};
finder = Finders.specializedFinder(queriesAnd);
res = finder.find(text());
LOGGER.info("the result of specialized(and) query[{}] is {}", queriesAnd, res);
finder = Finders.advancedFinder("it was","kingdom","sea");
res = finder.find(text());
LOGGER.info("the result of advanced query is {}", res);
res = Finders.filteredFinder(" was ", "many", "child").find(text());
LOGGER.info("the result of filtered query is {}", res);
}
private static String text() {
return
"It was many and many a year ago,\n"
+ "In a kingdom by the sea,\n"
+ "That a maiden there lived whom you may know\n"
+ "By the name of ANNABEL LEE;\n"
+ "And this maiden she lived with no other thought\n"
+ "Than to love and be loved by me.\n"
+ "I was a child and she was a child,\n"
+ "In this kingdom by the sea;\n"
+ "But we loved with a love that was more than love-\n"
+ "I and my Annabel Lee;\n"
+ "With a love that the winged seraphs of heaven\n"
+ "Coveted her and me.";
}
}

View File

@ -0,0 +1,93 @@
/*
* The MIT License
* Copyright © 2014-2019 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.combinator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Functional interface to find lines in text.
*/
public interface Finder {
/**
* The function to find lines in text.
* @param text full tet
* @return result of searching
*/
List<String> find(String text);
/**
* Simple implementation of function {@link #find(String)}.
* @param word for searching
* @return this
*/
static Finder contains(String word) {
return txt -> Stream.of(txt.split("\n"))
.filter(line -> line.toLowerCase().contains(word.toLowerCase()))
.collect(Collectors.toList());
}
/**
* combinator not.
* @param notFinder finder to combine
* @return new finder including previous finders
*/
default Finder not(Finder notFinder) {
return txt -> {
List<String> res = this.find(txt);
res.removeAll(notFinder.find(txt));
return res;
};
}
/**
* combinator or.
* @param orFinder finder to combine
* @return new finder including previous finders
*/
default Finder or(Finder orFinder) {
return txt -> {
List<String> res = this.find(txt);
res.addAll(orFinder.find(txt));
return res;
};
}
/**
* combinator or.
* @param andFinder finder to combine
* @return new finder including previous finders
*/
default Finder and(Finder andFinder) {
return
txt -> this
.find(txt)
.stream()
.flatMap(line -> andFinder.find(line).stream())
.collect(Collectors.toList());
}
}

View File

@ -0,0 +1,103 @@
/*
* The MIT License
* Copyright © 2014-2019 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.combinator;
import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Complex finders consisting of simple finder.
*/
public class Finders {
private Finders() {
}
/**
* Finder to find a complex query.
* @param query to find
* @param orQuery alternative to find
* @param notQuery exclude from search
* @return new finder
*/
public static Finder advancedFinder(String query, String orQuery, String notQuery) {
return
Finder.contains(query)
.or(Finder.contains(orQuery))
.not(Finder.contains(notQuery));
}
/**
* Filtered finder looking a query with excluded queries as well.
* @param query to find
* @param excludeQueries to exclude
* @return new finder
*/
public static Finder filteredFinder(String query, String... excludeQueries) {
var finder = Finder.contains(query);
for (String q : excludeQueries) {
finder = finder.not(Finder.contains(q));
}
return finder;
}
/**
* Specialized query. Every next query is looked in previous result.
* @param queries array with queries
* @return new finder
*/
public static Finder specializedFinder(String... queries) {
var finder = identMult();
for (String query : queries) {
finder = finder.and(Finder.contains(query));
}
return finder;
}
/**
* Expanded query. Looking for alternatives.
* @param queries array with queries.
* @return new finder
*/
public static Finder expandedFinder(String... queries) {
var finder = identSum();
for (String query : queries) {
finder = finder.or(Finder.contains(query));
}
return finder;
}
private static Finder identMult() {
return txt -> Stream.of(txt.split("\n")).collect(Collectors.toList());
}
private static Finder identSum() {
return txt -> new ArrayList<>();
}
}

View File

@ -0,0 +1,36 @@
/*
* The MIT License
* Copyright © 2014-2019 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.combinator;
import org.junit.Test;
import static org.junit.Assert.*;
public class CombinatorAppTest {
@Test
public void main() {
CombinatorApp.main(new String[]{});
}
}

View File

@ -0,0 +1,44 @@
/*
* The MIT License
* Copyright © 2014-2019 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.combinator;
import org.junit.Assert;
import org.junit.Test;
import java.util.List;
import static org.junit.Assert.*;
public class FinderTest {
@Test
public void contains() {
var example = "the first one \nthe second one \n";
var result = Finder.contains("second").find(example);
Assert.assertEquals(result.size(),1);
Assert.assertEquals(result.get(0),"the second one ");
}
}

View File

@ -0,0 +1,83 @@
/*
* The MIT License
* Copyright © 2014-2019 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.combinator;
import org.junit.Assert;
import org.junit.Test;
import java.util.List;
import static com.iluwatar.combinator.Finders.*;
import static org.junit.Assert.*;
public class FindersTest {
@Test
public void advancedFinderTest() {
var res = advancedFinder("it was","kingdom","sea").find(text());
Assert.assertEquals(res.size(),1);
Assert.assertEquals(res.get(0),"It was many and many a year ago,");
}
@Test
public void filteredFinderTest() {
var res = filteredFinder(" was ", "many", "child").find(text());
Assert.assertEquals(res.size(),1);
Assert.assertEquals(res.get(0),"But we loved with a love that was more than love-");
}
@Test
public void specializedFinderTest() {
var res = specializedFinder("love","heaven").find(text());
Assert.assertEquals(res.size(),1);
Assert.assertEquals(res.get(0),"With a love that the winged seraphs of heaven");
}
@Test
public void expandedFinderTest() {
var res = expandedFinder("It was","kingdom").find(text());
Assert.assertEquals(res.size(),3);
Assert.assertEquals(res.get(0),"It was many and many a year ago,");
Assert.assertEquals(res.get(1),"In a kingdom by the sea,");
Assert.assertEquals(res.get(2),"In this kingdom by the sea;");
}
private String text(){
return
"It was many and many a year ago,\n"
+ "In a kingdom by the sea,\n"
+ "That a maiden there lived whom you may know\n"
+ "By the name of ANNABEL LEE;\n"
+ "And this maiden she lived with no other thought\n"
+ "Than to love and be loved by me.\n"
+ "I was a child and she was a child,\n"
+ "In this kingdom by the sea;\n"
+ "But we loved with a love that was more than love-\n"
+ "I and my Annabel Lee;\n"
+ "With a love that the winged seraphs of heaven\n"
+ "Coveted her and me.";
}
}