Skip to content

Commit

Permalink
support synonyms recognizing pantry items
Browse files Browse the repository at this point in the history
  • Loading branch information
barneyb committed Mar 31, 2024
1 parent 1c0b5fe commit 04c9d5a
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 6 deletions.
8 changes: 8 additions & 0 deletions src/main/java/com/brennaswitzer/cookbook/domain/Named.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,13 @@
public interface Named {

String getName();

/**
* Whether this Named answers to the given name. The default implementation
* simply checks case-insensitive equality. No Named ever answers to null.
*/
default boolean answersToName(String name) {
return name != null && name.equalsIgnoreCase(getName());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ public void setName(String name) {
super.setName(name);
}

@Override
public boolean answersToName(String name) {
return super.answersToName(name)
|| hasSynonym(name);
}

public boolean hasSynonym(String synonym) {
if (synonyms == null) return false;
if (synonym == null || synonym.isBlank()) return false;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,32 @@
package com.brennaswitzer.cookbook.repositories;

import com.brennaswitzer.cookbook.domain.PantryItem;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;

import java.time.Instant;
import java.util.List;

public interface PantryItemRepository extends CrudRepository<PantryItem, Long> {

@Query("""
select item
from PantryItem item
left join item.synonyms syn
where upper(item.name) = upper(:name)
or upper(syn) = upper(:name)
order by item.id
""")
List<PantryItem> findByNameIgnoreCaseOrderById(String name);

@Query("""
select item
from PantryItem item
left join item.synonyms syn
where upper(item.name) like upper('%' || :name || '%') escape '\\'
or upper(syn) like upper('%' || :name || '%') escape '\\'
order by item.id
""")
List<PantryItem> findAllByNameIgnoreCaseContainingOrderById(String name);

List<PantryItem> findAllByUpdatedAtIsAfter(Instant cutoff);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;

Expand All @@ -39,7 +38,7 @@ public Ingredient ensureIngredientByName(String name) {
return pantryItemRepository.save(new PantryItem(EnglishUtils.unpluralize(name)));
}

public Iterable<Ingredient> findAllIngredientsByNameContaining(String name) {
public List<Ingredient> findAllIngredientsByNameContaining(String name) {
String unpluralized = EnglishUtils.unpluralize(name);
List<PantryItem> pantryItems = pantryItemRepository.findAllByNameIgnoreCaseContainingOrderById(unpluralized);
List<Ingredient> result = new ArrayList<>(pantryItems);
Expand Down Expand Up @@ -77,7 +76,7 @@ public Optional<? extends Ingredient> findIngredientByName(String name) {
public Iterable<Ingredient> findAllIngredientsByNamesContaining(List<String> names) {
List<Ingredient> results = new ArrayList<>();
for (String name : names) {
results.addAll((Collection<? extends Ingredient>) findAllIngredientsByNameContaining(name));
results.addAll(findAllIngredientsByNameContaining(name));
}
return results;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,8 @@ public Optional<RecognizedRange> multiPass(Iterable<RecognizedRange> ranges, Str

for (Phrase phrase : phrases) {
for (Ingredient opt : options) {
if (phrase.getCanonical().equals(opt.getName())
|| phrase.getOriginal().equalsIgnoreCase(opt.getName())) {
if (opt.answersToName(phrase.getCanonical())
|| opt.answersToName(phrase.getOriginal())) {
Phrase match = phrase.of(RecognizedRangeType.ITEM)
.withId(opt.getId());
if (best == null || Phrase.BY_LENGTH.compare(match, best) > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,18 @@ void synonyms() {
assertTrue(it.hasSynonym("stilton")); // ignore case
}

@Test
void answersToName() {
val it = new PantryItem("the curd-y stuff");
it.addSynonyms("cheese", "Cheez", "CHEEZE");

assertFalse(it.answersToName("curd-y stuff"));
assertTrue(it.answersToName("THE curd-y STUFF"));

assertTrue(it.answersToName("cheese"));
assertTrue(it.answersToName("cheeze"));
assertTrue(it.answersToName("CHEEZ"));
assertFalse(it.answersToName("cheese stick"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,39 @@ public void recognizeItem() {
assertFalse(ri.hasNext());
}

@Test
public void recognizeImplicitSynonym() {
RecipeBox box = new RecipeBox();
box.persist(entityManager, principalAccess.getUser());

final String RAW = "sea nacl, ground fine";
RecognizedItem el = recognizeItem(RAW);
System.out.println(el);

assertEquals(RAW, el.getRaw());
Iterator<RecognizedRange> ri = el.getRanges().iterator();
RecognizedRange saltRange = ri.next();
assertEquals(new RecognizedRange(4, 8, RecognizedRangeType.ITEM), saltRange);
assertEquals(box.salt.getId(), saltRange.getId());
assertFalse(ri.hasNext());
}

@Test
public void recognizeExplicitSynonym() {
RecipeBox box = new RecipeBox();
box.persist(entityManager, principalAccess.getUser());

final String RAW = "sea \"nacl\", ground fine";
RecognizedItem el = recognizeItem(RAW);
System.out.println(el);

assertEquals(RAW, el.getRaw());
Iterator<RecognizedRange> ri = el.getRanges().iterator();
RecognizedRange saltRange = ri.next();
assertEquals(box.salt.getId(), saltRange.getId());
assertFalse(ri.hasNext());
}

@Test
public void recognizeItemMultipleNoCase() {
RecipeBox box = new RecipeBox();
Expand Down Expand Up @@ -262,7 +295,6 @@ public void buildMultiwordPhrases() {
//noinspection OptionalGetWithoutIsPresent
RecognizedRange ing = ri.filter(it -> it.getType() == RecognizedRangeType.ITEM).findFirst().get();
assertEquals(new RecognizedRange(0, 18, RecognizedRangeType.ITEM), ing);

}

private RecognizedItem recognizeItem(String raw) {
Expand Down
1 change: 1 addition & 0 deletions src/test/resources/application-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ spring:
datasource:
# This is the PostgreSQL version we target. Keep it in sync.
url: jdbc:tc:postgresql:15.6:///postgres
jpa.show-sql: true
app:
aws:
access-key: oh-my-its-so-glergy
Expand Down

0 comments on commit 04c9d5a

Please sign in to comment.