diff --git a/core/src/main/java/com/graphhopper/reader/osm/ConditionalTagsInspector.java b/core/src/main/java/com/graphhopper/reader/osm/ConditionalTagsInspector.java
new file mode 100644
index 00000000000..4c12a4bbbd4
--- /dev/null
+++ b/core/src/main/java/com/graphhopper/reader/osm/ConditionalTagsInspector.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to GraphHopper and Peter Karich under one or more contributor
+ * license agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * GraphHopper licenses this file to you 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 com.graphhopper.reader.osm;
+
+import com.graphhopper.reader.OSMWay;
+import com.graphhopper.reader.osm.conditional.ConditionalParser;
+import com.graphhopper.reader.osm.conditional.DateRange;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Calendar;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Inspects the conditional tags of an OSMWay according to the given conditional tags.
+ *
+ * @author Robin Boldt
+ */
+public class ConditionalTagsInspector
+{
+
+ private static final Logger logger = LoggerFactory.getLogger(ConditionalTagsInspector.class);
+
+ private final Calendar calendar;
+ private final List tagsToCheck;
+ private final ConditionalParser restrictiveParser;
+ private final ConditionalParser permitParser;
+ private final boolean enabledLogs = false;
+
+ /**
+ * Create with todays date
+ */
+ public ConditionalTagsInspector( List tagsToCheck, Set restrictiveValues, Set permittedValues )
+ {
+ this(Calendar.getInstance(), tagsToCheck, restrictiveValues, permittedValues);
+ }
+
+ /**
+ * Create with given date
+ */
+ public ConditionalTagsInspector( Calendar date, List tagsToCheck, Set restrictiveValues, Set permittedValues )
+ {
+ this.calendar = date;
+ this.tagsToCheck = tagsToCheck;
+ this.restrictiveParser = new ConditionalParser(restrictiveValues, enabledLogs);
+ this.permitParser = new ConditionalParser(permittedValues, enabledLogs);
+ }
+
+ public boolean isRestrictedWayConditionallyPermitted( OSMWay way )
+ {
+ return applies(way, true);
+ }
+
+ public boolean isPermittedWayConditionallyRestricted( OSMWay way )
+ {
+ return applies(way, false);
+ }
+
+ protected boolean applies( OSMWay way, boolean checkPermissiveValues )
+ {
+ for (String tagToCheck : tagsToCheck)
+ {
+ tagToCheck = tagToCheck + ":conditional";
+ String val = way.getTag(tagToCheck);
+ if (val != null && !val.isEmpty())
+ {
+ try
+ {
+ DateRange dateRange;
+ if (checkPermissiveValues)
+ dateRange = permitParser.getDateRange(val);
+ else
+ dateRange = restrictiveParser.getDateRange(val);
+
+ if (dateRange != null && dateRange.isInRange(calendar))
+ return true;
+ } catch (Exception e)
+ {
+ if (enabledLogs)
+ logger.warn("Could not parse the conditional value:" + val + " of tag:" + tagToCheck + ". Exception:" + e.getMessage());
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/core/src/main/java/com/graphhopper/reader/osm/conditional/ConditionalParser.java b/core/src/main/java/com/graphhopper/reader/osm/conditional/ConditionalParser.java
new file mode 100644
index 00000000000..67f518b51b5
--- /dev/null
+++ b/core/src/main/java/com/graphhopper/reader/osm/conditional/ConditionalParser.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to GraphHopper and Peter Karich under one or more contributor
+ * license agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * GraphHopper licenses this file to you 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 com.graphhopper.reader.osm.conditional;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.text.ParseException;
+import java.util.Set;
+
+/**
+ * Parses a conditional tag according to
+ * http://wiki.openstreetmap.org/wiki/Conditional_restrictions.
+ *
+ * @author Robin Boldt
+ */
+public class ConditionalParser
+{
+
+ private final Set restrictedTags;
+ private static final Logger logger = LoggerFactory.getLogger(ConditionalParser.class);
+ private final boolean enabledLogs;
+
+ public ConditionalParser( Set restrictedTags )
+ {
+ this(restrictedTags, false);
+ }
+
+ public ConditionalParser( Set restrictedTags, boolean enabledLogs )
+ {
+ this.restrictedTags = restrictedTags;
+ this.enabledLogs = enabledLogs;
+ }
+
+ public DateRange getDateRange( String conditionalTag ) throws ParseException
+ {
+
+ if (conditionalTag == null || conditionalTag.isEmpty() || !conditionalTag.contains("@"))
+ return null;
+
+ if (conditionalTag.contains(";"))
+ {
+ // TODO #374
+ if (enabledLogs)
+ logger.warn("We do not support multiple conditions yet: " + conditionalTag);
+ return null;
+ }
+
+ String[] conditionalArr = conditionalTag.split("@");
+
+ if (conditionalArr.length != 2)
+ throw new IllegalStateException("could not split this condition: " + conditionalTag);
+
+ String restrictiveValue = conditionalArr[0].trim();
+ if (!restrictedTags.contains(restrictiveValue))
+ return null;
+
+ String conditional = conditionalArr[1];
+ conditional = conditional.replace('(', ' ');
+ conditional = conditional.replace(')', ' ');
+ conditional = conditional.trim();
+
+ return DateRangeParser.parseDateRange(conditional);
+ }
+
+}
diff --git a/core/src/main/java/com/graphhopper/reader/osm/conditional/DateRange.java b/core/src/main/java/com/graphhopper/reader/osm/conditional/DateRange.java
new file mode 100644
index 00000000000..27d6a2693b5
--- /dev/null
+++ b/core/src/main/java/com/graphhopper/reader/osm/conditional/DateRange.java
@@ -0,0 +1,136 @@
+package com.graphhopper.reader.osm.conditional;
+
+import java.util.Calendar;
+
+/**
+ * This class represents a date range and is able to determine if a given date is in that range.
+ *
+ * @author Robin Boldt
+ */
+public class DateRange
+{
+ private Calendar from;
+ private Calendar to;
+
+ // Do not compare years
+ boolean yearless = false;
+
+ boolean dayOnly = false;
+
+ boolean reverse = false;
+
+ // TODO Gets to complex? Create Factory?
+ public DateRange( ParsedCalendar from, ParsedCalendar to )
+ {
+ Calendar fromCal = from.parsedCalendar;
+ Calendar toCal = to.parsedCalendar;
+
+ // This should never happen
+ if (fromCal.get(Calendar.ERA) != fromCal.get(Calendar.ERA))
+ {
+ throw new IllegalArgumentException("Different ERAs are not allowed. From:" + from + " To:" + to);
+ }
+
+ if (from.isYearless() && to.isYearless())
+ {
+ yearless = true;
+ }
+
+ if (from.isDayOnly() && to.isDayOnly())
+ {
+ dayOnly = true;
+ }
+
+ if (fromCal.after(toCal))
+ {
+ if (!yearless && !dayOnly)
+ {
+ throw new IllegalArgumentException("From after to makes no sense, except for isYearless and isDayOnly DateRanges. From:" + from + " To:" + to);
+ } else
+ {
+ reverse = true;
+ }
+ }
+
+ this.from = from.getMin();
+ this.to = to.getMax();
+
+ }
+
+ public boolean isInRange( Calendar date )
+ {
+ if (!yearless && !dayOnly)
+ return date.after(from) && date.before(to);
+
+ if(dayOnly){
+ if(reverse){
+ return (from.get(Calendar.DAY_OF_WEEK) <= date.get(Calendar.DAY_OF_WEEK) || date.get(Calendar.DAY_OF_WEEK) <= to.get(Calendar.DAY_OF_WEEK));
+ }else{
+ return (from.get(Calendar.DAY_OF_WEEK) <= date.get(Calendar.DAY_OF_WEEK) && date.get(Calendar.DAY_OF_WEEK) <= to.get(Calendar.DAY_OF_WEEK));
+ }
+ }
+
+ if (reverse)
+ return isInRangeYearlessReverse(date);
+ else
+ return isInRangeYearless(date);
+ }
+
+ private boolean isInRangeYearless( Calendar date )
+ {
+ if (from.get(Calendar.MONTH) < date.get(Calendar.MONTH) && date.get(Calendar.MONTH) < to.get(Calendar.MONTH))
+ return true;
+ if (from.get(Calendar.MONTH) == date.get(Calendar.MONTH) && to.get(Calendar.MONTH) == date.get(Calendar.MONTH))
+ {
+ if (from.get(Calendar.DAY_OF_MONTH) <= date.get(Calendar.DAY_OF_MONTH) && date.get(Calendar.DAY_OF_MONTH) <= to.get(Calendar.DAY_OF_MONTH))
+ return true;
+ else
+ return false;
+ }
+ if (from.get(Calendar.MONTH) == date.get(Calendar.MONTH))
+ {
+ if (from.get(Calendar.DAY_OF_MONTH) <= date.get(Calendar.DAY_OF_MONTH))
+ return true;
+ else
+ return false;
+ }
+ if (to.get(Calendar.MONTH) == date.get(Calendar.MONTH))
+ {
+ if (date.get(Calendar.DAY_OF_MONTH) <= to.get(Calendar.DAY_OF_MONTH))
+ return true;
+ else
+ return false;
+ }
+ return false;
+ }
+
+ private boolean isInRangeYearlessReverse( Calendar date )
+ {
+ if (from.get(Calendar.MONTH) < date.get(Calendar.MONTH) || date.get(Calendar.MONTH) < to.get(Calendar.MONTH))
+ return true;
+ if (from.get(Calendar.MONTH) == date.get(Calendar.MONTH) && to.get(Calendar.MONTH) == date.get(Calendar.MONTH))
+ {
+ if (from.get(Calendar.DAY_OF_MONTH) < date.get(Calendar.DAY_OF_MONTH) || date.get(Calendar.DAY_OF_MONTH) < to.get(Calendar.DAY_OF_MONTH))
+ return true;
+ else
+ return false;
+ }
+ if (from.get(Calendar.MONTH) == date.get(Calendar.MONTH))
+ {
+ if (from.get(Calendar.DAY_OF_MONTH) <= date.get(Calendar.DAY_OF_MONTH))
+ return true;
+ else
+ return false;
+ }
+ if (to.get(Calendar.MONTH) == date.get(Calendar.MONTH))
+ {
+ if (date.get(Calendar.DAY_OF_MONTH) >= to.get(Calendar.DAY_OF_MONTH))
+ return true;
+ else
+ return false;
+ }
+ return false;
+ }
+
+
+}
diff --git a/core/src/main/java/com/graphhopper/reader/osm/conditional/DateRangeParser.java b/core/src/main/java/com/graphhopper/reader/osm/conditional/DateRangeParser.java
new file mode 100644
index 00000000000..d05e9a0cc27
--- /dev/null
+++ b/core/src/main/java/com/graphhopper/reader/osm/conditional/DateRangeParser.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to GraphHopper and Peter Karich under one or more contributor
+ * license agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * GraphHopper licenses this file to you 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 com.graphhopper.reader.osm.conditional;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.List;
+
+/**
+ * Parses a DateRange. Currently only DateRanges that last at least one day are supported. The
+ * Syntax is allowed inputs is described here: http://wiki.openstreetmap.org/wiki/Key:opening_hours.
+ *
+ * @author Robin Boldt
+ */
+public class DateRangeParser
+{
+ static SimpleDateFormat yearMonthDayFormat = new SimpleDateFormat("yyyy MMM dd");
+ static SimpleDateFormat monthDayFormat = new SimpleDateFormat("MMM dd");
+ static SimpleDateFormat monthDay2Format = new SimpleDateFormat("dd.MM");
+ static SimpleDateFormat yearMonthFormat = new SimpleDateFormat("yyyy MMM");
+ static SimpleDateFormat monthFormat = new SimpleDateFormat("MMM");
+ static SimpleDateFormat dayFormat = new SimpleDateFormat("E");
+ static List dayNames = Arrays.asList(new String[]
+ {
+ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"
+ });
+
+ public static ParsedCalendar parseDateString( String dateString ) throws ParseException
+ {
+ // Replace occurences of public holidays
+ dateString = dateString.replaceAll("(,( )*)?(PH|SH)", "");
+ dateString = dateString.trim();
+ Calendar calendar = Calendar.getInstance();
+ ParsedCalendar parsedCalendar;
+ try
+ {
+ calendar.setTime(yearMonthDayFormat.parse(dateString));
+ parsedCalendar = new ParsedCalendar(ParsedCalendar.ParseType.YEAR_MONTH_DAY, calendar);
+ } catch (ParseException e1)
+ {
+ try
+ {
+ calendar.setTime(monthDayFormat.parse(dateString));
+ parsedCalendar = new ParsedCalendar(ParsedCalendar.ParseType.MONTH_DAY, calendar);
+ } catch (ParseException e2)
+ {
+ try
+ {
+ calendar.setTime(monthDay2Format.parse(dateString));
+ parsedCalendar = new ParsedCalendar(ParsedCalendar.ParseType.MONTH_DAY, calendar);
+ } catch (ParseException e3)
+ {
+ try
+ {
+ calendar.setTime(yearMonthFormat.parse(dateString));
+ parsedCalendar = new ParsedCalendar(ParsedCalendar.ParseType.YEAR_MONTH, calendar);
+ } catch (ParseException e4)
+ {
+ try
+ {
+ calendar.setTime(monthFormat.parse(dateString));
+ parsedCalendar = new ParsedCalendar(ParsedCalendar.ParseType.MONTH, calendar);
+ } catch (ParseException e5)
+ {
+ int index = dayNames.indexOf(dateString);
+ if (index < 0)
+ throw new ParseException("Unparseable date: \"" + dateString + "\"", 0);
+
+ // Ranges from 1-7
+ calendar.set(Calendar.DAY_OF_WEEK, index + 1);
+ parsedCalendar = new ParsedCalendar(ParsedCalendar.ParseType.DAY, calendar);
+ }
+
+ }
+ }
+ }
+ }
+ return parsedCalendar;
+ }
+
+ public static DateRange parseDateRange( String dateRangeString ) throws ParseException
+ {
+ if (dateRangeString == null || dateRangeString.isEmpty())
+ throw new IllegalArgumentException("Passing empty Strings is not allowed");
+
+ String[] dateArr = dateRangeString.split("-");
+ if (dateArr.length > 2 || dateArr.length < 1)
+ throw new IllegalArgumentException("Only Strings containing two Date separated by a '-' or a single Date are allowed");
+
+ ParsedCalendar from = parseDateString(dateArr[0]);
+ ParsedCalendar to;
+ if (dateArr.length == 2)
+ to = parseDateString(dateArr[1]);
+ else
+ to = parseDateString(dateArr[0]);
+
+ return new DateRange(from, to);
+ }
+
+}
diff --git a/core/src/main/java/com/graphhopper/reader/osm/conditional/ParsedCalendar.java b/core/src/main/java/com/graphhopper/reader/osm/conditional/ParsedCalendar.java
new file mode 100644
index 00000000000..f26dedd655b
--- /dev/null
+++ b/core/src/main/java/com/graphhopper/reader/osm/conditional/ParsedCalendar.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to GraphHopper and Peter Karich under one or more contributor
+ * license agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * GraphHopper licenses this file to you 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 com.graphhopper.reader.osm.conditional;
+
+import java.util.Calendar;
+
+/**
+ * This class represents a parsed Date and the parse type.
+ *
+ * @author Robin Boldt
+ */
+public class ParsedCalendar
+{
+ public final ParseType parseType;
+ public final Calendar parsedCalendar;
+
+ public ParsedCalendar( ParseType parseType, Calendar parsedCalendar )
+ {
+ this.parseType = parseType;
+ this.parsedCalendar = parsedCalendar;
+ }
+
+ public boolean isYearless()
+ {
+ return parseType == ParseType.MONTH || parseType == ParseType.MONTH_DAY;
+ }
+
+ public boolean isDayless()
+ {
+ return parseType == ParseType.MONTH || parseType == ParseType.YEAR_MONTH;
+ }
+
+ public boolean isDayOnly()
+ {
+ return parseType == ParseType.DAY;
+ }
+
+ public Calendar getMax()
+ {
+ if (isDayless())
+ {
+ parsedCalendar.set(Calendar.DAY_OF_MONTH, parsedCalendar.getActualMaximum(Calendar.DAY_OF_MONTH));
+ }
+ parsedCalendar.set(Calendar.HOUR_OF_DAY, parsedCalendar.getActualMaximum(Calendar.HOUR_OF_DAY));
+ parsedCalendar.set(Calendar.MINUTE, parsedCalendar.getActualMaximum(Calendar.MINUTE));
+ parsedCalendar.set(Calendar.SECOND, parsedCalendar.getActualMaximum(Calendar.SECOND));
+ parsedCalendar.set(Calendar.MILLISECOND, parsedCalendar.getActualMaximum(Calendar.MILLISECOND));
+
+ return parsedCalendar;
+ }
+
+ public Calendar getMin()
+ {
+ if (isDayless())
+ {
+ parsedCalendar.set(Calendar.DAY_OF_MONTH, parsedCalendar.getActualMinimum(Calendar.DAY_OF_MONTH));
+ }
+ parsedCalendar.set(Calendar.HOUR_OF_DAY, parsedCalendar.getActualMinimum(Calendar.HOUR_OF_DAY));
+ parsedCalendar.set(Calendar.MINUTE, parsedCalendar.getActualMinimum(Calendar.MINUTE));
+ parsedCalendar.set(Calendar.SECOND, parsedCalendar.getActualMinimum(Calendar.SECOND));
+ parsedCalendar.set(Calendar.MILLISECOND, parsedCalendar.getActualMinimum(Calendar.MILLISECOND));
+
+ return parsedCalendar;
+ }
+
+ public enum ParseType
+ {
+ YEAR_MONTH_DAY,
+ YEAR_MONTH,
+ MONTH_DAY,
+ MONTH,
+ DAY
+ }
+
+}
diff --git a/core/src/main/java/com/graphhopper/routing/util/AbstractFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/AbstractFlagEncoder.java
index 8cec00c00d4..d2d43ba5df9 100644
--- a/core/src/main/java/com/graphhopper/routing/util/AbstractFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/AbstractFlagEncoder.java
@@ -17,6 +17,7 @@
*/
package com.graphhopper.routing.util;
+import com.graphhopper.reader.osm.ConditionalTagsInspector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -83,6 +84,8 @@ public abstract class AbstractFlagEncoder implements FlagEncoder, TurnCostEncode
protected final double speedFactor;
private boolean registered;
+ protected ConditionalTagsInspector conditionalTagsInspector;
+
public AbstractFlagEncoder( PMap properties )
{
throw new RuntimeException("This method must be overridden in derived classes");
@@ -820,4 +823,5 @@ public boolean supports( Class> feature )
return false;
}
+
}
diff --git a/core/src/main/java/com/graphhopper/routing/util/BikeCommonFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/BikeCommonFlagEncoder.java
index 0374c21a58d..6ae39e15eb2 100644
--- a/core/src/main/java/com/graphhopper/routing/util/BikeCommonFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/BikeCommonFlagEncoder.java
@@ -17,17 +17,17 @@
*/
package com.graphhopper.routing.util;
-import com.graphhopper.reader.OSMWay;
import com.graphhopper.reader.OSMRelation;
-
-import static com.graphhopper.routing.util.PriorityCode.*;
-
+import com.graphhopper.reader.OSMWay;
+import com.graphhopper.reader.osm.ConditionalTagsInspector;
import com.graphhopper.util.Helper;
import com.graphhopper.util.InstructionAnnotation;
import com.graphhopper.util.Translation;
import java.util.*;
+import static com.graphhopper.routing.util.PriorityCode.*;
+
/**
* Defines bit layout of bicycles (not motorcycles) for speed, access and relations (network).
*
@@ -199,6 +199,8 @@ protected BikeCommonFlagEncoder( int speedBits, double speedFactor, int maxTurnC
setCyclingNetworkPreference("deprecated", PriorityCode.AVOID_AT_ALL_COSTS.getValue());
setAvoidSpeedLimit(71);
+
+ conditionalTagsInspector = new ConditionalTagsInspector(restrictions, restrictedValues, intendedValues);
}
@Override
@@ -274,7 +276,7 @@ public long acceptWay( OSMWay way )
return 0;
// check access restrictions
- if (way.hasTag(restrictions, restrictedValues))
+ if (way.hasTag(restrictions, restrictedValues) && !conditionalTagsInspector.isRestrictedWayConditionallyPermitted(way))
return 0;
// do not accept railways (sometimes incorrectly mapped!)
@@ -290,7 +292,11 @@ public long acceptWay( OSMWay way )
if (!allowedSacScale(sacScale))
return 0;
}
- return acceptBit;
+
+ if (conditionalTagsInspector.isPermittedWayConditionallyRestricted(way))
+ return 0;
+ else
+ return acceptBit;
}
boolean allowedSacScale( String sacScale )
diff --git a/core/src/main/java/com/graphhopper/routing/util/CarFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/CarFlagEncoder.java
index aaeee662bd2..eb416d8a4ac 100644
--- a/core/src/main/java/com/graphhopper/routing/util/CarFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/CarFlagEncoder.java
@@ -17,13 +17,9 @@
*/
package com.graphhopper.routing.util;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
import com.graphhopper.reader.OSMRelation;
import com.graphhopper.reader.OSMWay;
+import com.graphhopper.reader.osm.ConditionalTagsInspector;
import com.graphhopper.util.Helper;
import com.graphhopper.util.PMap;
@@ -135,6 +131,8 @@ public CarFlagEncoder( int speedBits, double speedFactor, int maxTurnCosts )
defaultSpeedMap.put("road", 20);
// forestry stuff
defaultSpeedMap.put("track", 15);
+
+ conditionalTagsInspector = new ConditionalTagsInspector(restrictions, restrictedValues, intendedValues);
}
@Override
@@ -180,6 +178,7 @@ protected double getSpeed( OSMWay way )
@Override
public long acceptWay( OSMWay way )
{
+ // TODO: Ferries have conditionals, like opening hours or are closed during some time in the year
String highwayValue = way.getTag("highway");
if (highwayValue == null)
{
@@ -212,7 +211,7 @@ public long acceptWay( OSMWay way )
String firstValue = way.getFirstPriorityTag(restrictions);
if (!firstValue.isEmpty())
{
- if (restrictedValues.contains(firstValue))
+ if (restrictedValues.contains(firstValue) && !conditionalTagsInspector.isRestrictedWayConditionallyPermitted(way))
return 0;
if (intendedValues.contains(firstValue))
return acceptBit;
@@ -226,7 +225,10 @@ public long acceptWay( OSMWay way )
if (way.hasTag("railway") && !way.hasTag("railway", acceptedRailways))
return 0;
- return acceptBit;
+ if (conditionalTagsInspector.isPermittedWayConditionallyRestricted(way))
+ return 0;
+ else
+ return acceptBit;
}
@Override
diff --git a/core/src/main/java/com/graphhopper/routing/util/FootFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/FootFlagEncoder.java
index 2e9252f9c3a..dc6ed4cb342 100644
--- a/core/src/main/java/com/graphhopper/routing/util/FootFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/FootFlagEncoder.java
@@ -17,17 +17,15 @@
*/
package com.graphhopper.routing.util;
-import java.util.HashSet;
-import java.util.Set;
-
import com.graphhopper.reader.OSMRelation;
import com.graphhopper.reader.OSMWay;
+import com.graphhopper.reader.osm.ConditionalTagsInspector;
import com.graphhopper.util.PMap;
-import static com.graphhopper.routing.util.PriorityCode.*;
-
import java.util.*;
+import static com.graphhopper.routing.util.PriorityCode.*;
+
/**
* Defines bit layout for pedestrians (speed, access, surface, ...).
*
@@ -131,6 +129,8 @@ public FootFlagEncoder( int speedBits, double speedFactor )
hikingNetworkToCode.put("lwn", VERY_NICE.getValue());
maxPossibleSpeed = FERRY_SPEED;
+
+ conditionalTagsInspector = new ConditionalTagsInspector(restrictions, restrictedValues, intendedValues);
}
@Override
@@ -248,14 +248,17 @@ public long acceptWay( OSMWay way )
return 0;
// check access restrictions
- if (way.hasTag(restrictions, restrictedValues))
+ if (way.hasTag(restrictions, restrictedValues) && !conditionalTagsInspector.isRestrictedWayConditionallyPermitted(way))
return 0;
// do not accept railways (sometimes incorrectly mapped!)
if (way.hasTag("railway") && !way.hasTag("railway", acceptedRailways))
return 0;
- return acceptBit;
+ if (conditionalTagsInspector.isPermittedWayConditionallyRestricted(way))
+ return 0;
+ else
+ return acceptBit;
}
@Override
diff --git a/core/src/main/java/com/graphhopper/routing/util/MotorcycleFlagEncoder.java b/core/src/main/java/com/graphhopper/routing/util/MotorcycleFlagEncoder.java
index bc21d6c9d02..7f824b537de 100644
--- a/core/src/main/java/com/graphhopper/routing/util/MotorcycleFlagEncoder.java
+++ b/core/src/main/java/com/graphhopper/routing/util/MotorcycleFlagEncoder.java
@@ -18,14 +18,15 @@
package com.graphhopper.routing.util;
import com.graphhopper.reader.OSMWay;
+import com.graphhopper.reader.osm.ConditionalTagsInspector;
import com.graphhopper.util.BitUtil;
import com.graphhopper.util.EdgeIteratorState;
import com.graphhopper.util.PMap;
-import static com.graphhopper.routing.util.PriorityCode.*;
-
import java.util.HashSet;
+import static com.graphhopper.routing.util.PriorityCode.BEST;
+
/**
* Defines bit layout for motorbikes
*
@@ -117,6 +118,7 @@ public MotorcycleFlagEncoder( int speedBits, double speedFactor, int maxTurnCost
// forestry stuff
defaultSpeedMap.put("track", 15);
+ conditionalTagsInspector = new ConditionalTagsInspector(restrictions, restrictedValues, intendedValues);
}
@Override
@@ -180,7 +182,7 @@ public long acceptWay( OSMWay way )
String firstValue = way.getFirstPriorityTag(restrictions);
if (!firstValue.isEmpty())
{
- if (restrictedValues.contains(firstValue))
+ if (restrictedValues.contains(firstValue) && !conditionalTagsInspector.isRestrictedWayConditionallyPermitted(way))
return 0;
if (intendedValues.contains(firstValue))
return acceptBit;
@@ -194,7 +196,10 @@ public long acceptWay( OSMWay way )
if (way.hasTag("railway") && !way.hasTag("railway", acceptedRailways))
return 0;
- return acceptBit;
+ if (conditionalTagsInspector.isPermittedWayConditionallyRestricted(way))
+ return 0;
+ else
+ return acceptBit;
}
@Override
diff --git a/core/src/test/java/com/graphhopper/reader/osm/CalendarBasedTest.java b/core/src/test/java/com/graphhopper/reader/osm/CalendarBasedTest.java
new file mode 100644
index 00000000000..deb92248338
--- /dev/null
+++ b/core/src/test/java/com/graphhopper/reader/osm/CalendarBasedTest.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to GraphHopper and Peter Karich under one or more contributor
+ * license agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * GraphHopper licenses this file to you 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 com.graphhopper.reader.osm;
+
+import java.util.Calendar;
+
+/**
+ * Base Test for calendar based tasks.
+ *
+ * @author Robin Boldt
+ */
+public abstract class CalendarBasedTest
+{
+
+ protected Calendar getCalendar( int year, int month, int day )
+ {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(Calendar.YEAR, year);
+ calendar.set(Calendar.MONTH, month);
+ calendar.set(Calendar.DAY_OF_MONTH, day);
+ return calendar;
+ }
+
+}
diff --git a/core/src/test/java/com/graphhopper/reader/osm/ConditionalTagsInspectorTest.java b/core/src/test/java/com/graphhopper/reader/osm/ConditionalTagsInspectorTest.java
new file mode 100644
index 00000000000..208900cedfe
--- /dev/null
+++ b/core/src/test/java/com/graphhopper/reader/osm/ConditionalTagsInspectorTest.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to GraphHopper and Peter Karich under one or more contributor
+ * license agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * GraphHopper licenses this file to you 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 com.graphhopper.reader.osm;
+
+import com.graphhopper.reader.OSMWay;
+import org.junit.Test;
+
+import java.util.*;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Robin Boldt
+ */
+public class ConditionalTagsInspectorTest extends CalendarBasedTest
+{
+ @Test
+ public void testConditionalAccept()
+ {
+ Calendar cal = getCalendar(2014, Calendar.MARCH, 10);
+ ConditionalTagsInspector acceptor = new ConditionalTagsInspector(cal, getSampleConditionalTags(), getSampleRestrictedValues(), getSamplePermissiveValues());
+ OSMWay way = new OSMWay(1);
+ way.setTag("vehicle:conditional", "no @ (Aug 10-Aug 14)");
+ assertFalse(acceptor.isPermittedWayConditionallyRestricted(way));
+ }
+
+ @Test
+ public void testConditionalAcceptNextYear()
+ {
+ Calendar cal = getCalendar(2014, Calendar.MARCH, 10);
+ ConditionalTagsInspector acceptor = new ConditionalTagsInspector(cal, getSampleConditionalTags(), getSampleRestrictedValues(), getSamplePermissiveValues());
+ OSMWay way = new OSMWay(1);
+ way.setTag("vehicle:conditional", "no @ (2013 Mar 1-2013 Mar 31)");
+ assertFalse(acceptor.isPermittedWayConditionallyRestricted(way));
+ }
+
+ @Test
+ public void testConditionalReject()
+ {
+ Calendar cal = getCalendar(2014, Calendar.MARCH, 10);
+ ConditionalTagsInspector acceptor = new ConditionalTagsInspector(cal, getSampleConditionalTags(), getSampleRestrictedValues(), getSamplePermissiveValues());
+ OSMWay way = new OSMWay(1);
+ way.setTag("vehicle:conditional", "no @ (Mar 10-Aug 14)");
+ assertTrue(acceptor.isPermittedWayConditionallyRestricted(way));
+ }
+
+ @Test
+ public void testConditionalAllowance()
+ {
+ Calendar cal = getCalendar(2014, Calendar.MARCH, 10);
+ ConditionalTagsInspector acceptor = new ConditionalTagsInspector(cal, getSampleConditionalTags(), getSampleRestrictedValues(), getSamplePermissiveValues());
+ OSMWay way = new OSMWay(1);
+ way.setTag("vehicle:conditional", "yes @ (Mar 10-Aug 14)");
+ assertTrue(acceptor.isRestrictedWayConditionallyPermitted(way));
+ }
+
+ @Test
+ public void testConditionalAllowanceReject()
+ {
+ Calendar cal = getCalendar(2014, Calendar.MARCH, 10);
+ ConditionalTagsInspector acceptor = new ConditionalTagsInspector(cal, getSampleConditionalTags(), getSampleRestrictedValues(), getSamplePermissiveValues());
+ OSMWay way = new OSMWay(1);
+ way.setTag("vehicle:conditional", "no @ (Mar 10-Aug 14)");
+ assertTrue(acceptor.isPermittedWayConditionallyRestricted(way));
+ }
+
+ @Test
+ public void testConditionalSingleDay()
+ {
+ Calendar cal = getCalendar(2015, Calendar.DECEMBER, 27);
+ ConditionalTagsInspector acceptor = new ConditionalTagsInspector(cal, getSampleConditionalTags(), getSampleRestrictedValues(), getSamplePermissiveValues());
+ OSMWay way = new OSMWay(1);
+ way.setTag("vehicle:conditional", "no @ (Su)");
+ assertTrue(acceptor.isPermittedWayConditionallyRestricted(way));
+ }
+
+ @Test
+ public void testConditionalAllowanceSingleDay()
+ {
+ Calendar cal = getCalendar(2015, Calendar.DECEMBER, 27);
+ ConditionalTagsInspector acceptor = new ConditionalTagsInspector(cal, getSampleConditionalTags(), getSampleRestrictedValues(), getSamplePermissiveValues());
+ OSMWay way = new OSMWay(1);
+ way.setTag("vehicle:conditional", "yes @ (Su)");
+ assertTrue(acceptor.isRestrictedWayConditionallyPermitted(way));
+ }
+
+ private static Set getSampleRestrictedValues()
+ {
+ Set restrictedValues = new HashSet();
+ restrictedValues.add("private");
+ restrictedValues.add("agricultural");
+ restrictedValues.add("forestry");
+ restrictedValues.add("no");
+ restrictedValues.add("restricted");
+ restrictedValues.add("delivery");
+ restrictedValues.add("military");
+ restrictedValues.add("emergency");
+ return restrictedValues;
+ }
+
+ private static Set getSamplePermissiveValues()
+ {
+ Set restrictedValues = new HashSet();
+ restrictedValues.add("yes");
+ restrictedValues.add("permissive");
+ return restrictedValues;
+ }
+
+ private static List getSampleConditionalTags()
+ {
+ List conditionalTags = new ArrayList();
+ conditionalTags.add("vehicle");
+ conditionalTags.add("access");
+ return conditionalTags;
+ }
+
+}
diff --git a/core/src/test/java/com/graphhopper/reader/osm/conditional/ConditionalParserTest.java b/core/src/test/java/com/graphhopper/reader/osm/conditional/ConditionalParserTest.java
new file mode 100644
index 00000000000..f401427ebfd
--- /dev/null
+++ b/core/src/test/java/com/graphhopper/reader/osm/conditional/ConditionalParserTest.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to GraphHopper and Peter Karich under one or more contributor
+ * license agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * GraphHopper licenses this file to you 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 com.graphhopper.reader.osm.conditional;
+
+import com.graphhopper.reader.OSMWay;
+import com.graphhopper.reader.osm.CalendarBasedTest;
+import com.graphhopper.reader.osm.ConditionalTagsInspector;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.text.ParseException;
+import java.util.Calendar;
+import java.util.HashSet;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Robin Boldt
+ */
+public class ConditionalParserTest extends CalendarBasedTest
+{
+
+ ConditionalParser parser;
+
+ @Before
+ public void setup()
+ {
+ HashSet restrictedValues = new HashSet();
+ restrictedValues.add("private");
+ restrictedValues.add("agricultural");
+ restrictedValues.add("forestry");
+ restrictedValues.add("no");
+ restrictedValues.add("restricted");
+ restrictedValues.add("delivery");
+ restrictedValues.add("military");
+ restrictedValues.add("emergency");
+
+ parser = new ConditionalParser(restrictedValues);
+ }
+
+ @Test
+ public void testParseConditional() throws ParseException
+ {
+ DateRange dateRange = parser.getDateRange("no @ (2015 Sep 1-2015 Sep 30)");
+ assertFalse(dateRange.isInRange(getCalendar(2015, Calendar.AUGUST, 31)));
+ assertTrue(dateRange.isInRange(getCalendar(2015, Calendar.SEPTEMBER, 30)));
+ }
+
+ @Test
+ public void testParseAllowingCondition() throws ParseException
+ {
+ DateRange dateRange = parser.getDateRange("yes @ (2015 Sep 1-2015 Sep 30)");
+ assertNull(dateRange);
+ }
+
+ @Test
+ public void testParsingOfLeading0() throws ParseException
+ {
+ DateRange dateRange = parser.getDateRange("no @ (01.11. - 31.03.)");
+ assertTrue(dateRange.isInRange(getCalendar(2015, Calendar.DECEMBER, 2)));
+
+ dateRange = parser.getDateRange("no @ (01.11 - 31.03)");
+ assertTrue(dateRange.isInRange(getCalendar(2015, Calendar.DECEMBER, 2)));
+ }
+}
diff --git a/core/src/test/java/com/graphhopper/reader/osm/conditional/DateRangeParserTest.java b/core/src/test/java/com/graphhopper/reader/osm/conditional/DateRangeParserTest.java
new file mode 100644
index 00000000000..304b0411e24
--- /dev/null
+++ b/core/src/test/java/com/graphhopper/reader/osm/conditional/DateRangeParserTest.java
@@ -0,0 +1,209 @@
+/*
+ * Licensed to GraphHopper and Peter Karich under one or more contributor
+ * license agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * GraphHopper licenses this file to you 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 com.graphhopper.reader.osm.conditional;
+
+import com.graphhopper.reader.osm.CalendarBasedTest;
+import org.junit.Test;
+
+import java.text.ParseException;
+import java.util.Calendar;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Robin Boldt
+ */
+public class DateRangeParserTest extends CalendarBasedTest
+{
+ @Test
+ public void testParseConditional() throws ParseException
+ {
+ assertSameDate(2014, Calendar.DECEMBER, 15, "2014 Dec 15");
+ assertSameDate(2015, Calendar.MARCH, 2, "2015 Mar 2");
+ assertSameDate(2015, Calendar.MARCH, 1, "2015 Mar");
+ assertSameDate(1970, Calendar.MARCH, 31, "Mar 31");
+ assertSameDate(1970, Calendar.DECEMBER, 1, "Dec");
+ }
+
+ @Test
+ public void testParseSimpleDateRange() throws ParseException
+ {
+ DateRange dateRange = DateRangeParser.parseDateRange("2014 Aug 10-2014 Aug 14");
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 9)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 10)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 12)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 14)));
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 15)));
+ }
+
+ @Test
+ public void testParseSimpleDateRangeWithoutYear() throws ParseException
+ {
+ DateRange dateRange = DateRangeParser.parseDateRange("Aug 10-Aug 14");
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 9)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 10)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 12)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 14)));
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 15)));
+ }
+
+ @Test
+ public void testParseSimpleDateRangeWithoutYearAndDay() throws ParseException
+ {
+ DateRange dateRange = DateRangeParser.parseDateRange("Jul-Aug");
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.JUNE, 9)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.JULY, 10)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 12)));
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.SEPTEMBER, 14)));
+ }
+
+ @Test
+ public void testParseSimpleDateRangeWithoutYearAndDay2() throws ParseException
+ {
+ DateRange dateRange = DateRangeParser.parseDateRange("Mar-Sep");
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.FEBRUARY, 25)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.MARCH, 1)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.SEPTEMBER, 30)));
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.NOVEMBER, 1)));
+ }
+
+ @Test
+ public void testParseReverseDateRange() throws ParseException
+ {
+ DateRange dateRange = DateRangeParser.parseDateRange("2014 Aug 14-2015 Mar 10");
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 13)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 14)));
+ assertTrue(dateRange.isInRange(getCalendar(2015, Calendar.MARCH, 10)));
+ assertFalse(dateRange.isInRange(getCalendar(2015, Calendar.MARCH, 11)));
+ }
+
+ @Test
+ public void testParseReverseDateRangeWithoutYear() throws ParseException
+ {
+ DateRange dateRange = DateRangeParser.parseDateRange("Aug 14-Aug 10");
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.JANUARY, 9)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 9)));
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 10)));
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 12)));
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 14)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 15)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.SEPTEMBER, 15)));
+ }
+
+ @Test
+ public void testParseReverseDateRangeWithoutYearAndDay() throws ParseException
+ {
+ DateRange dateRange = DateRangeParser.parseDateRange("Sep-Mar");
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 31)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.SEPTEMBER, 1)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.DECEMBER, 24)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.JANUARY, 24)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.MARCH, 31)));
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.APRIL, 1)));
+ }
+
+ @Test
+ public void testParseSingleDateRange() throws ParseException
+ {
+ DateRange dateRange = DateRangeParser.parseDateRange("2014 Sep 1");
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 31)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.SEPTEMBER, 1)));
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.SEPTEMBER, 30)));
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.OCTOBER, 1)));
+ assertFalse(dateRange.isInRange(getCalendar(2015, Calendar.SEPTEMBER, 1)));
+ }
+
+ @Test
+ public void testParseSingleDateRangeWithoutDay() throws ParseException
+ {
+ DateRange dateRange = DateRangeParser.parseDateRange("2014 Sep");
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 31)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.SEPTEMBER, 1)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.SEPTEMBER, 30)));
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.OCTOBER, 1)));
+ assertFalse(dateRange.isInRange(getCalendar(2015, Calendar.SEPTEMBER, 1)));
+ }
+
+ @Test
+ public void testParseSingleDateRangeWithoutYearAndDay() throws ParseException
+ {
+ DateRange dateRange = DateRangeParser.parseDateRange("Sep");
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.AUGUST, 31)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.SEPTEMBER, 1)));
+ assertTrue(dateRange.isInRange(getCalendar(2014, Calendar.SEPTEMBER, 30)));
+ assertFalse(dateRange.isInRange(getCalendar(2014, Calendar.OCTOBER, 1)));
+ }
+
+ @Test
+ public void testParseSingleDateRangeOneDayOnly() throws ParseException
+ {
+ DateRange dateRange = DateRangeParser.parseDateRange("Sa");
+ assertFalse(dateRange.isInRange(getCalendar(2015, Calendar.DECEMBER, 25)));
+ assertTrue(dateRange.isInRange(getCalendar(2015, Calendar.DECEMBER, 26)));
+ assertFalse(dateRange.isInRange(getCalendar(2015, Calendar.DECEMBER, 27)));
+ }
+
+ @Test
+ public void testParseSingleDateRangeOneDayOnlyIncludingPh() throws ParseException
+ {
+ DateRange dateRange = DateRangeParser.parseDateRange("Su, PH");
+ assertFalse(dateRange.isInRange(getCalendar(2015, Calendar.DECEMBER, 26)));
+ assertTrue(dateRange.isInRange(getCalendar(2015, Calendar.DECEMBER, 27)));
+ assertFalse(dateRange.isInRange(getCalendar(2015, Calendar.DECEMBER, 28)));
+ }
+
+ @Test
+ public void testParseSingleDateRangeDayOnly() throws ParseException
+ {
+ DateRange dateRange = DateRangeParser.parseDateRange("Mo-Fr");
+ assertFalse(dateRange.isInRange(getCalendar(2015, Calendar.DECEMBER, 20)));
+ assertTrue(dateRange.isInRange(getCalendar(2015, Calendar.DECEMBER, 21)));
+ assertTrue(dateRange.isInRange(getCalendar(2015, Calendar.DECEMBER, 25)));
+ assertFalse(dateRange.isInRange(getCalendar(2015, Calendar.DECEMBER, 26)));
+ assertTrue(dateRange.isInRange(getCalendar(2015, Calendar.DECEMBER, 28)));
+ }
+
+ @Test
+ public void testParseReverseDateRangeDayOnly() throws ParseException
+ {
+ // This is reverse since Sa=7 and So=1
+ DateRange dateRange = DateRangeParser.parseDateRange("Sa-Su");
+ assertFalse(dateRange.isInRange(getCalendar(2015, Calendar.DECEMBER, 25)));
+ assertTrue(dateRange.isInRange(getCalendar(2015, Calendar.DECEMBER, 26)));
+ assertTrue(dateRange.isInRange(getCalendar(2015, Calendar.DECEMBER, 27)));
+ assertFalse(dateRange.isInRange(getCalendar(2015, Calendar.DECEMBER, 28)));
+ }
+
+ @Test(expected = ParseException.class)
+ public void testParseUnparsableDate() throws ParseException
+ {
+ DateRangeParser.parseDateRange("Sat");
+ fail();
+ }
+
+ private void assertSameDate( int year, int month, int day, String dateString ) throws ParseException
+ {
+ Calendar expected = getCalendar(year, month, day);
+ ParsedCalendar actualParsed = DateRangeParser.parseDateString(dateString);
+ Calendar actual = actualParsed.parsedCalendar;
+ assertEquals(expected.get(Calendar.YEAR), actual.get(Calendar.YEAR));
+ assertEquals(expected.get(Calendar.MONTH), actual.get(Calendar.MONTH));
+ assertEquals(expected.get(Calendar.DAY_OF_MONTH), actual.get(Calendar.DAY_OF_MONTH));
+ }
+
+}
diff --git a/core/src/test/java/com/graphhopper/routing/util/AbstractBikeFlagEncoderTester.java b/core/src/test/java/com/graphhopper/routing/util/AbstractBikeFlagEncoderTester.java
index 2f9d07c2155..83153f2fecd 100644
--- a/core/src/test/java/com/graphhopper/routing/util/AbstractBikeFlagEncoderTester.java
+++ b/core/src/test/java/com/graphhopper/routing/util/AbstractBikeFlagEncoderTester.java
@@ -19,20 +19,18 @@
import com.graphhopper.reader.OSMNode;
import com.graphhopper.reader.OSMWay;
-
-import static com.graphhopper.routing.util.PriorityCode.*;
-
import com.graphhopper.util.Translation;
+import org.junit.Before;
+import org.junit.Test;
-import static com.graphhopper.util.TranslationMapTest.SINGLETON;
-
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
import java.util.Locale;
+import static com.graphhopper.routing.util.PriorityCode.*;
+import static com.graphhopper.util.TranslationMapTest.SINGLETON;
import static org.junit.Assert.*;
-import org.junit.Before;
-import org.junit.Test;
-
/**
* @author Peter Karich
* @author ratrun
@@ -174,6 +172,20 @@ public void testAccess()
way.setTag("cycleway", "track");
way.setTag("railway", "abandoned");
assertTrue(encoder.acceptWay(way) > 0);
+
+ Calendar calendar = Calendar.getInstance();
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy MMM dd");
+
+ way.clearTags();
+ way.setTag("highway", "road");
+ way.setTag("bicycle:conditional", "no @ (" + simpleDateFormat.format(calendar.getTime()) + ")");
+ assertFalse(encoder.acceptWay(way) > 0);
+
+ way.clearTags();
+ way.setTag("highway", "road");
+ way.setTag("access", "no");
+ way.setTag("bicycle:conditional", "yes @ (" + simpleDateFormat.format(calendar.getTime()) + ")");
+ assertTrue(encoder.acceptWay(way) > 0);
}
@Test
diff --git a/core/src/test/java/com/graphhopper/routing/util/CarFlagEncoderTest.java b/core/src/test/java/com/graphhopper/routing/util/CarFlagEncoderTest.java
index 40b4df9c82e..dbf97c91351 100644
--- a/core/src/test/java/com/graphhopper/routing/util/CarFlagEncoderTest.java
+++ b/core/src/test/java/com/graphhopper/routing/util/CarFlagEncoderTest.java
@@ -21,6 +21,9 @@
import com.graphhopper.reader.OSMWay;
import org.junit.Test;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
import static org.junit.Assert.*;
/**
@@ -107,6 +110,20 @@ public void testAccess()
way.setTag("highway", "service");
way.setTag("motor_vehicle", "emergency");
assertFalse(encoder.acceptWay(way) > 0);
+
+ Calendar calendar = Calendar.getInstance();
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy MMM dd");
+
+ way.clearTags();
+ way.setTag("highway", "road");
+ way.setTag("access:conditional", "no @ ("+simpleDateFormat.format(calendar.getTime())+")");
+ assertFalse(encoder.acceptWay(way) > 0);
+
+ way.clearTags();
+ way.setTag("highway", "road");
+ way.setTag("access", "no");
+ way.setTag("access:conditional", "yes @ ("+simpleDateFormat.format(calendar.getTime())+")");
+ assertTrue(encoder.acceptWay(way) > 0);
}
@Test
diff --git a/core/src/test/java/com/graphhopper/routing/util/FootFlagEncoderTest.java b/core/src/test/java/com/graphhopper/routing/util/FootFlagEncoderTest.java
index e84f759031d..f91655a93b0 100644
--- a/core/src/test/java/com/graphhopper/routing/util/FootFlagEncoderTest.java
+++ b/core/src/test/java/com/graphhopper/routing/util/FootFlagEncoderTest.java
@@ -26,6 +26,9 @@
import org.junit.Test;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
import static org.junit.Assert.*;
/**
@@ -154,6 +157,20 @@ public void testAccess()
assertTrue(footEncoder.acceptWay(way) > 0);
way.setTag("foot", "no");
assertFalse(footEncoder.acceptWay(way) > 0);
+
+ Calendar calendar = Calendar.getInstance();
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy MMM dd");
+
+ way.clearTags();
+ way.setTag("highway", "footway");
+ way.setTag("access:conditional", "no @ ("+simpleDateFormat.format(calendar.getTime())+")");
+ assertFalse(footEncoder.acceptWay(way) > 0);
+
+ way.clearTags();
+ way.setTag("highway", "footway");
+ way.setTag("access", "no");
+ way.setTag("access:conditional", "yes @ ("+simpleDateFormat.format(calendar.getTime())+")");
+ assertTrue(footEncoder.acceptWay(way) > 0);
}
@Test
diff --git a/core/src/test/java/com/graphhopper/routing/util/MotorcycleFlagEncoderTest.java b/core/src/test/java/com/graphhopper/routing/util/MotorcycleFlagEncoderTest.java
index 8e7934592f3..e78be6226d6 100644
--- a/core/src/test/java/com/graphhopper/routing/util/MotorcycleFlagEncoderTest.java
+++ b/core/src/test/java/com/graphhopper/routing/util/MotorcycleFlagEncoderTest.java
@@ -22,9 +22,11 @@
import com.graphhopper.util.EdgeIteratorState;
import com.graphhopper.util.GHUtility;
import com.graphhopper.util.Helper;
-import com.graphhopper.util.PointList;
import org.junit.Test;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
import static org.junit.Assert.*;
/**
@@ -50,6 +52,81 @@ private Graph initExampleGraph()
return gs;
}
+ @Test
+ public void testAccess()
+ {
+ OSMWay way = new OSMWay(1);
+ assertFalse(encoder.acceptWay(way) > 0);
+ way.setTag("highway", "service");
+ assertTrue(encoder.acceptWay(way) > 0);
+ way.setTag("access", "no");
+ assertFalse(encoder.acceptWay(way) > 0);
+
+ way.clearTags();
+ way.setTag("highway", "track");
+ assertTrue(encoder.acceptWay(way) > 0);
+
+ way.clearTags();
+ way.setTag("highway", "service");
+ way.setTag("access", "delivery");
+ assertFalse(encoder.acceptWay(way) > 0);
+
+ way.clearTags();
+ way.setTag("highway", "unclassified");
+ way.setTag("ford", "yes");
+ assertFalse(encoder.acceptWay(way) > 0);
+ way.setTag("motorcycle", "yes");
+ assertTrue(encoder.acceptWay(way) > 0);
+
+ way.clearTags();
+ way.setTag("route", "ferry");
+ assertTrue(encoder.acceptWay(way) > 0);
+ assertTrue(encoder.isFerry(encoder.acceptWay(way)));
+ way.setTag("motorcycle", "no");
+ assertFalse(encoder.acceptWay(way) > 0);
+
+ way.clearTags();
+ way.setTag("route", "ferry");
+ way.setTag("foot", "yes");
+ assertFalse(encoder.acceptWay(way) > 0);
+ assertFalse(encoder.isFerry(encoder.acceptWay(way)));
+
+ way.clearTags();
+ way.setTag("access", "yes");
+ way.setTag("motor_vehicle", "no");
+ assertFalse(encoder.acceptWay(way) > 0);
+
+ way.clearTags();
+ way.setTag("highway", "service");
+ way.setTag("access", "yes");
+ way.setTag("motor_vehicle", "no");
+ assertFalse(encoder.acceptWay(way) > 0);
+
+ way.clearTags();
+ way.setTag("highway", "service");
+ way.setTag("access", "emergency");
+ assertFalse(encoder.acceptWay(way) > 0);
+
+ way.clearTags();
+ way.setTag("highway", "service");
+ way.setTag("motor_vehicle", "emergency");
+ assertFalse(encoder.acceptWay(way) > 0);
+
+ Calendar calendar = Calendar.getInstance();
+ SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy MMM dd");
+
+ way.clearTags();
+ way.setTag("highway", "road");
+ way.setTag("access:conditional", "no @ ("+simpleDateFormat.format(calendar.getTime())+")");
+ assertFalse(encoder.acceptWay(way) > 0);
+
+ way.clearTags();
+ way.setTag("highway", "road");
+ way.setTag("access", "no");
+ way.setTag("access:conditional", "yes @ ("+simpleDateFormat.format(calendar.getTime())+")");
+ assertTrue(encoder.acceptWay(way) > 0);
+ }
+
@Test
public void testHandleWayTags()
{