suumo-search

Perform advanced searches on Suumo.jp
git clone https://git.neuralcrash.com/suumo-search.git
Log | Files | Refs | README

SearchConditionsValidator.java (5670B)


      1 package xyz.kebigon.housesearch.domain;
      2 
      3 import java.util.Arrays;
      4 import java.util.Collection;
      5 import java.util.stream.Stream;
      6 
      7 import org.springframework.expression.Expression;
      8 import org.springframework.expression.ExpressionParser;
      9 import org.springframework.expression.spel.standard.SpelExpressionParser;
     10 import org.springframework.expression.spel.support.StandardEvaluationContext;
     11 
     12 import lombok.AllArgsConstructor;
     13 import lombok.extern.slf4j.Slf4j;
     14 import xyz.kebigon.housesearch.ApplicationContext;
     15 
     16 @AllArgsConstructor
     17 @Slf4j
     18 public class SearchConditionsValidator
     19 {
     20 	public static boolean validateBasicConditions(Posting posting, SearchConditions conditions)
     21 	{
     22 		final String url = posting.getUrl();
     23 		if (url == null)
     24 		{
     25 			log.debug("Missing url for {}", posting);
     26 			return false;
     27 		}
     28 
     29 		final Long price = posting.getPrice();
     30 		if (price == null)
     31 		{
     32 			log.debug("Missing price for {}", posting);
     33 			return false;
     34 		}
     35 		if (conditions.getMinPrice() != null && price < conditions.getMinPrice())
     36 			return false;
     37 		if (conditions.getMaxPrice() != null && price > conditions.getMaxPrice())
     38 			return false;
     39 
     40 		final Integer age = posting.getAge();
     41 		if (age == null)
     42 		{
     43 			log.debug("Missing age for {}", posting);
     44 			return false;
     45 		}
     46 		if (conditions.getMinAge() != null && age < conditions.getMinAge())
     47 			return false;
     48 		if (conditions.getMaxAge() != null && age > conditions.getMaxAge())
     49 			return false;
     50 
     51 		final Double landSurface = posting.getLandSurface();
     52 		if (landSurface == null)
     53 		{
     54 			log.debug("Missing landSurface for {}", posting);
     55 			return false;
     56 		}
     57 		if (conditions.getMinLandSurface() != null && landSurface < conditions.getMinLandSurface())
     58 			return false;
     59 		if (conditions.getMaxLandSurface() != null && landSurface > conditions.getMaxLandSurface())
     60 			return false;
     61 
     62 		final Double houseSurface = posting.getHouseSurface();
     63 		if (houseSurface == null)
     64 		{
     65 			log.debug("Missing houseSurface for {}", posting);
     66 			return false;
     67 		}
     68 		if (conditions.getMinHouseSurface() != null && houseSurface < conditions.getMinHouseSurface())
     69 			return false;
     70 		if (conditions.getMaxHouseSurface() != null && houseSurface > conditions.getMaxHouseSurface())
     71 			return false;
     72 
     73 		final Integer walkTimeToStation = posting.getWalkTimeToStation();
     74 		if (walkTimeToStation == null)
     75 		{
     76 			log.debug("Missing walkTimeToStation for {}", posting);
     77 			return false;
     78 		}
     79 		if (conditions.getMaxWalkTimeToStation() != null && walkTimeToStation > conditions.getMaxWalkTimeToStation())
     80 			return false;
     81 
     82 		final String station = posting.getStation();
     83 		if (station == null)
     84 		{
     85 			log.debug("Missing station for {}", posting);
     86 			return false;
     87 		}
     88 
     89 		return true;
     90 	}
     91 
     92 	public static boolean validateExpression(Posting posting, SearchConditions conditions)
     93 	{
     94 		final ExpressionParser expressionParser = new SpelExpressionParser();
     95 
     96 		final StandardEvaluationContext context = new StandardEvaluationContext();
     97 		context.setVariable("property", posting);
     98 
     99 		try
    100 		{
    101 			context.registerFunction("fastestRoute",
    102 					SearchConditionsValidator.class.getDeclaredMethod("getFastestRoute", new Class[] { Posting.class, String[].class }));
    103 			context.registerFunction("cheapestRoute",
    104 					SearchConditionsValidator.class.getDeclaredMethod("getCheapestRoute", new Class[] { Posting.class, String[].class }));
    105 			context.registerFunction("easiestRoute",
    106 					SearchConditionsValidator.class.getDeclaredMethod("getEasiestRoute", new Class[] { Posting.class, String[].class }));
    107 
    108 			context.registerFunction("timeToStation",
    109 					SearchConditionsValidator.class.getDeclaredMethod("timeToStation", new Class[] { Posting.class, String.class }));
    110 			context.registerFunction("fareToStation",
    111 					SearchConditionsValidator.class.getDeclaredMethod("fareToStation", new Class[] { Posting.class, String.class }));
    112 			context.registerFunction("transferToStation",
    113 					SearchConditionsValidator.class.getDeclaredMethod("transferToStation", new Class[] { Posting.class, String.class }));
    114 		}
    115 		catch (NoSuchMethodException | SecurityException e)
    116 		{
    117 			e.printStackTrace();
    118 			throw new RuntimeException(e);
    119 		}
    120 
    121 		final Expression expression = expressionParser.parseExpression(conditions.getExpression());
    122 		return expression.getValue(context, posting, Boolean.class);
    123 	}
    124 
    125 	private static Stream<Route> getRoutes(Posting posting, String... stations)
    126 	{
    127 		return Arrays.stream(stations) //
    128 				.flatMap(station -> {
    129 					final Collection<Route> routes = ApplicationContext.getYahooTransitBrowser().search(posting.getStation(), station);
    130 					routes.forEach(posting::updateRoutes);
    131 					return routes.stream();
    132 				});
    133 	}
    134 
    135 	private static Route getFastestRoute(Posting posting, String... stations)
    136 	{
    137 		return getRoutes(posting, stations).min(Route.TIME_COMPARATOR).orElse(Route.IMPOSSIBLE_ROUTE);
    138 	}
    139 
    140 	private static Route getCheapestRoute(Posting posting, String... stations)
    141 	{
    142 		return getRoutes(posting, stations).min(Route.FARE_COMPARATOR).orElse(Route.IMPOSSIBLE_ROUTE);
    143 	}
    144 
    145 	private static Route getEasiestRoute(Posting posting, String... stations)
    146 	{
    147 		return getRoutes(posting, stations).min(Route.TRANSFER_COMPARATOR).orElse(Route.IMPOSSIBLE_ROUTE);
    148 	}
    149 
    150 	@SuppressWarnings("unused")
    151 	private static int timeToStation(Posting posting, String station)
    152 	{
    153 		return getFastestRoute(posting, station).getTime() + posting.getWalkTimeToStation();
    154 	}
    155 
    156 	@SuppressWarnings("unused")
    157 	private static int fareToStation(Posting posting, String station)
    158 	{
    159 		return getCheapestRoute(posting, station).getFare();
    160 	}
    161 
    162 	@SuppressWarnings("unused")
    163 	private static int transferToStation(Posting posting, String station)
    164 	{
    165 		return getEasiestRoute(posting, station).getTransfer();
    166 	}
    167 }