diff --git a/OsmAnd-java/src/net/osmand/util/OpeningHoursParser.java b/OsmAnd-java/src/net/osmand/util/OpeningHoursParser.java index 4a19db2612..6345f47bb8 100644 --- a/OsmAnd-java/src/net/osmand/util/OpeningHoursParser.java +++ b/OsmAnd-java/src/net/osmand/util/OpeningHoursParser.java @@ -8,9 +8,11 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Set; import gnu.trove.list.array.TIntArrayList; @@ -27,6 +29,7 @@ public class OpeningHoursParser { private static final String[] localDaysStr; private static final String[] monthsStr; private static final String[] localMothsStr; + private static final Map additionalStrings = new HashMap<>(); private static final int LOW_TIME_LIMIT = 120; private static final int WITHOUT_TIME_LIMIT = -1; @@ -39,6 +42,23 @@ public class OpeningHoursParser { dateFormatSymbols = DateFormatSymbols.getInstance(); localMothsStr = dateFormatSymbols.getShortMonths(); localDaysStr = getTwoLettersStringArray(dateFormatSymbols.getShortWeekdays()); + + additionalStrings.put("off", "off"); + additionalStrings.put("is_open", "Open"); + additionalStrings.put("is_open_24_7", "Open 24/7"); + additionalStrings.put("will_open_at", "Will open at"); + additionalStrings.put("open_from", "Open from"); + additionalStrings.put("will_close_at", "Will close at"); + additionalStrings.put("open_till", "Open till"); + additionalStrings.put("will_open_tomorrow_at", "Will open tomorrow at"); + additionalStrings.put("will_open_on", "Will open on"); + } + + /** + * Set additional localized strings like "off", etc. + */ + public static void setAdditionalString(String key, String value) { + additionalStrings.put(key, value); } /** @@ -89,11 +109,61 @@ public class OpeningHoursParser { */ public static class OpeningHours implements Serializable { + public static final int ALL_SEQUENCES = -1; + /** * list of the different rules */ private ArrayList rules; private String original; + private int sequenceCount; + + public static class Info { + + private boolean opened; + private boolean opened24_7; + private String openingTime; + private String nearToOpeningTime; + private String closingTime; + private String nearToClosingTime; + private String openingTomorrow; + private String openingDay; + private String ruleString; + + public boolean isOpened() { + return opened; + } + + public boolean isOpened24_7() { + return opened24_7; + } + + public String getInfo() { + if (isOpened24_7()) { + if (!Algorithms.isEmpty(ruleString)) { + return additionalStrings.get("is_open") + " " + ruleString; + } else { + return additionalStrings.get("is_open_24_7"); + } + } else if (!Algorithms.isEmpty(nearToOpeningTime)) { + return additionalStrings.get("will_open_at") + " " + nearToOpeningTime; + } else if (!Algorithms.isEmpty(openingTime)) { + return additionalStrings.get("open_from") + " " + openingTime; + } else if (!Algorithms.isEmpty(nearToClosingTime)) { + return additionalStrings.get("will_close_at") + " " + nearToClosingTime; + } else if (!Algorithms.isEmpty(closingTime)) { + return additionalStrings.get("open_till") + " " + closingTime; + } else if (!Algorithms.isEmpty(openingTomorrow)) { + return additionalStrings.get("will_open_tomorrow_at") + " " + openingTomorrow; + } else if (!Algorithms.isEmpty(openingDay)) { + return additionalStrings.get("will_open_on") + " " + openingDay + "."; + } else if (!Algorithms.isEmpty(ruleString)) { + return ruleString; + } else { + return ""; + } + } + } /** * Constructor @@ -111,6 +181,45 @@ public class OpeningHoursParser { rules = new ArrayList(); } + public List getInfo() { + return getInfo(Calendar.getInstance()); + } + + public List getInfo(Calendar cal) { + List res = new ArrayList<>(); + for (int i = 0; i < sequenceCount; i++) { + Info info = getInfo(cal, i); + res.add(info); + } + return res.isEmpty() ? null : res; + } + + public Info getCombinedInfo() { + return getCombinedInfo(Calendar.getInstance()); + } + + public Info getCombinedInfo(Calendar cal) { + return getInfo(cal, ALL_SEQUENCES); + } + + private Info getInfo(Calendar cal, int sequenceIndex) { + Info info = new Info(); + boolean opened = isOpenedForTimeV2(cal, sequenceIndex); + info.opened = opened; + info.ruleString = getCurrentRuleTime(cal, sequenceIndex); + if (opened) { + info.opened24_7 = isOpened24_7(sequenceIndex); + info.closingTime = getClosingTime(cal, sequenceIndex); + info.nearToClosingTime = getNearToClosingTime(cal, sequenceIndex); + } else { + info.openingTime = getOpeningTime(cal, sequenceIndex); + info.nearToOpeningTime = getNearToOpeningTime(cal, sequenceIndex); + info.openingTomorrow = getOpeningTomorrow(cal, sequenceIndex); + info.openingDay = getOpeningDay(cal, sequenceIndex); + } + return info; + } + /** * add a rule to the opening hours * @@ -125,10 +234,18 @@ public class OpeningHoursParser { * * @param rules to add */ - public void addRules(List rules) { + public void addRules(List rules) { this.rules.addAll(rules); } + public int getSequenceCount() { + return sequenceCount; + } + + public void setSequenceCount(int sequenceCount) { + this.sequenceCount = sequenceCount; + } + /** * return the list of rules * @@ -137,32 +254,47 @@ public class OpeningHoursParser { public ArrayList getRules() { return rules; } - + + public ArrayList getRules(int sequenceIndex) { + if (sequenceIndex == ALL_SEQUENCES) { + return rules; + } else { + ArrayList sequenceRules = new ArrayList<>(); + for (OpeningHoursRule r : rules) { + if (r.getSequenceIndex() == sequenceIndex) { + sequenceRules.add(r); + } + } + return sequenceRules; + } + } + /** * check if the feature is opened at time "cal" * * @param cal the time to check * @return true if feature is open */ - public boolean isOpenedForTimeV2(Calendar cal) { + public boolean isOpenedForTimeV2(Calendar cal, int sequenceIndex) { // make exception for overlapping times i.e. // (1) Mo 14:00-16:00; Tu off // (2) Mo 14:00-02:00; Tu off // in (2) we need to check first rule even though it is against specification + ArrayList rules = getRules(sequenceIndex); boolean overlap = false; - for(int i = rules.size() - 1; i >= 0 ; i--) { + for (int i = rules.size() - 1; i >= 0 ; i--) { OpeningHoursRule r = rules.get(i); - if(r.hasOverlapTimes()) { + if (r.hasOverlapTimes()) { overlap = true; break; } } // start from the most specific rule - for(int i = rules.size() - 1; i >= 0 ; i--) { + for (int i = rules.size() - 1; i >= 0 ; i--) { OpeningHoursRule r = rules.get(i); - if(r.contains(cal)) { + if (r.contains(cal)) { boolean open = r.isOpenedForTime(cal); - if(!open && overlap ) { + if (!open && overlap ) { continue; } else { return open; @@ -179,12 +311,24 @@ public class OpeningHoursParser { * @return true if feature is open */ public boolean isOpenedForTime(Calendar cal) { + return isOpenedForTimeV2(cal, ALL_SEQUENCES); + } + + /** + * check if the feature is opened at time "cal" + * + * @param cal the time to check + * @param sequenceIndex the sequence index to check + * @return true if feature is open + */ + public boolean isOpenedForTime(Calendar cal, int sequenceIndex) { /* * first check for rules that contain the current day * afterwards check for rules that contain the previous * day with overlapping times (times after midnight) */ boolean isOpenDay = false; + ArrayList rules = getRules(sequenceIndex); for (OpeningHoursRule r : rules) { if (r.containsDay(cal) && r.containsMonth(cal)) { isOpenDay = r.isOpenedForTime(cal, false); @@ -199,33 +343,48 @@ public class OpeningHoursParser { return isOpenDay || isOpenPrevious; } - public boolean isOpened24_7() { + public boolean isOpened24_7(int sequenceIndex) { boolean opened24_7 = false; + ArrayList rules = getRules(sequenceIndex); for (OpeningHoursRule r : rules) { opened24_7 = r.isOpened24_7(); } return opened24_7; } - public String getNearToOpeningTime(Calendar cal) { - return getTime(cal, LOW_TIME_LIMIT, true); + public String getNearToOpeningTime(Calendar cal, int sequenceIndex) { + return getTime(cal, LOW_TIME_LIMIT, true, sequenceIndex); } - public String getOpeningTime(Calendar cal) { - return getTime(cal, CURRENT_DAY_TIME_LIMIT, true); + public String getOpeningTime(Calendar cal, int sequenceIndex) { + return getTime(cal, CURRENT_DAY_TIME_LIMIT, true, sequenceIndex); } - public String getNearToClosingTime(Calendar cal) { - return getTime(cal, LOW_TIME_LIMIT, false); + public String getNearToClosingTime(Calendar cal, int sequenceIndex) { + return getTime(cal, LOW_TIME_LIMIT, false, sequenceIndex); } - public String getClosingTime(Calendar cal) { - return getTime(cal, WITHOUT_TIME_LIMIT, false); + public String getClosingTime(Calendar cal, int sequenceIndex) { + return getTime(cal, WITHOUT_TIME_LIMIT, false, sequenceIndex); } - public String getOpeningDay(Calendar calendar) { + public String getOpeningTomorrow(Calendar calendar, int sequenceIndex) { Calendar cal = (Calendar) calendar.clone(); String openingTime = ""; + ArrayList rules = getRules(sequenceIndex); + cal.add(Calendar.DAY_OF_MONTH, 1); + for (OpeningHoursRule r : rules) { + if (r.containsDay(cal) && r.containsMonth(cal)) { + openingTime = r.getTime(cal, false, WITHOUT_TIME_LIMIT, true); + } + } + return openingTime; + } + + public String getOpeningDay(Calendar calendar, int sequenceIndex) { + Calendar cal = (Calendar) calendar.clone(); + String openingTime = ""; + ArrayList rules = getRules(sequenceIndex); for (int i = 0; i < 7; i++) { cal.add(Calendar.DAY_OF_MONTH, 1); for (OpeningHoursRule r : rules) { @@ -241,16 +400,17 @@ public class OpeningHoursParser { return openingTime; } - private String getTime(Calendar cal, int limit, boolean opening) { - String time = getTimeDay(cal, limit, opening); + private String getTime(Calendar cal, int limit, boolean opening, int sequenceIndex) { + String time = getTimeDay(cal, limit, opening, sequenceIndex); if (Algorithms.isEmpty(time)) { - time = getTimeAnotherDay(cal, limit, opening); + time = getTimeAnotherDay(cal, limit, opening, sequenceIndex); } return time; } - private String getTimeDay(Calendar cal, int limit, boolean opening) { + private String getTimeDay(Calendar cal, int limit, boolean opening, int sequenceIndex) { String atTime = ""; + ArrayList rules = getRules(sequenceIndex); for (OpeningHoursRule r : rules) { if (r.containsDay(cal) && r.containsMonth(cal)) { atTime = r.getTime(cal, false, limit, opening); @@ -259,8 +419,9 @@ public class OpeningHoursParser { return atTime; } - private String getTimeAnotherDay(Calendar cal, int limit, boolean opening) { + private String getTimeAnotherDay(Calendar cal, int limit, boolean opening, int sequenceIndex) { String atTime = ""; + ArrayList rules = getRules(sequenceIndex); for (OpeningHoursRule r : rules) { if (((opening && r.containsPreviousDay(cal)) || (!opening && r.containsNextDay(cal))) && r.containsMonth(cal)) { atTime = r.getTime(cal, true, limit, opening); @@ -270,10 +431,15 @@ public class OpeningHoursParser { } public String getCurrentRuleTime(Calendar cal) { + return getCurrentRuleTime(cal, ALL_SEQUENCES); + } + + public String getCurrentRuleTime(Calendar cal, int sequenceIndex) { // make exception for overlapping times i.e. // (1) Mo 14:00-16:00; Tu off // (2) Mo 14:00-02:00; Tu off // in (2) we need to check first rule even though it is against specification + ArrayList rules = getRules(sequenceIndex); String ruleClosed = null; boolean overlap = false; for (int i = rules.size() - 1; i >= 0; i--) { @@ -428,6 +594,7 @@ public class OpeningHoursParser { */ public boolean contains(Calendar cal); + public int getSequenceIndex(); public String toRuleString(); @@ -475,6 +642,26 @@ public class OpeningHoursParser { */ private boolean off = false; + /** + * Aadditional information or limitation. + * https://wiki.openstreetmap.org/wiki/Key:opening_hours/specification#explain:comment + */ + private String comment; + + private int sequenceIndex; + + public BasicOpeningHourRule() { + this.sequenceIndex = 0; + } + + public BasicOpeningHourRule(int sequenceIndex) { + this.sequenceIndex = sequenceIndex; + } + + public int getSequenceIndex() { + return sequenceIndex; + } + /** * return an array representing the days of the rule * @@ -511,7 +698,14 @@ public class OpeningHoursParser { public boolean appliesToSchoolHolidays() { return schoolHoliday; } - + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } /** * set a single start time, erase all previously added start times @@ -786,27 +980,44 @@ public class OpeningHoursParser { appendDaysString(b, dayNames); // Time if (startTimes == null || startTimes.size() == 0) { - b.append("off"); + if (isOpened24_7()) { + b.setLength(0); + b.append("24/7 "); + } else if (off) { + b.append(additionalStrings.get("off")); + } } else { if (isOpened24_7()) { - return "24/7"; - } - for (int i = 0; i < startTimes.size(); i++) { - int startTime = startTimes.get(i); - int endTime = endTimes.get(i); - if(i > 0) { - b.append(", "); + b.setLength(0); + b.append("24/7"); + } else { + for (int i = 0; i < startTimes.size(); i++) { + int startTime = startTimes.get(i); + int endTime = endTimes.get(i); + if (i > 0) { + b.append(", "); + } + int stHour = startTime / 60; + int stTime = startTime - stHour * 60; + int enHour = endTime / 60; + int enTime = endTime - enHour * 60; + formatTime(stHour, stTime, b); + b.append("-"); //$NON-NLS-1$ + formatTime(enHour, enTime, b); + } + if (off) { + b.append(" ").append(additionalStrings.get("off")); } - int stHour = startTime / 60; - int stTime = startTime - stHour * 60; - int enHour = endTime / 60; - int enTime = endTime - enHour * 60; - formatTime(stHour, stTime, b); - b.append("-"); //$NON-NLS-1$ - formatTime(enHour, enTime, b); } - if(off) { - b.append(" off"); + } + if (!Algorithms.isEmpty(comment)) { + if (b.length() > 0) { + if (b.charAt(b.length() - 1) != ' ') { + b.append(" "); + } + b.append("(").append(comment).append(")"); + } else { + b.append(comment); } } return b.toString(); @@ -853,13 +1064,17 @@ public class OpeningHoursParser { } } - if (opened24_7 && startTimes != null && startTimes.size() > 0) { - for (int i = 0; i < startTimes.size(); i++) { - int startTime = startTimes.get(i); - int endTime = endTimes.get(i); - if (startTime == 0 && endTime / 60 == 24) { - return true; + if (opened24_7) { + if (startTimes != null && startTimes.size() > 0) { + for (int i = 0; i < startTimes.size(); i++) { + int startTime = startTimes.get(i); + int endTime = endTimes.get(i); + if (startTime == 0 && endTime / 60 == 24) { + return true; + } } + } else { + return true; } } return false; @@ -918,7 +1133,11 @@ public class OpeningHoursParser { } } } - return sb.toString(); + String res = sb.toString(); + if (res.length() > 0 && !Algorithms.isEmpty(comment)) { + res += " (" + comment + ")"; + } + return res; } @Override @@ -1015,7 +1234,7 @@ public class OpeningHoursParser { int c = calculate(cal); return c != 0; } - + @Override public boolean hasOverlapTimes() { for (int i = 0; i < startTimes.size(); i++) { @@ -1062,14 +1281,16 @@ public class OpeningHoursParser { } } } - if (thisDay && (startTimes == null || startTimes.isEmpty() || !off)) { + if (thisDay && (startTimes == null || startTimes.isEmpty()) && !off) { + return 1; + } else if (thisDay && (startTimes == null || startTimes.isEmpty() || !off)) { return -1; } return 0; } } - public static class UnparseableRule implements OpeningHoursParser.OpeningHoursRule { + public static class UnparseableRule implements OpeningHoursRule { private String ruleString; public UnparseableRule(String ruleString) { @@ -1140,6 +1361,11 @@ public class OpeningHoursParser { public boolean contains(Calendar cal) { return false; } + + @Override + public int getSequenceIndex() { + return 0; + } } private enum TokenType { @@ -1185,8 +1411,22 @@ public class OpeningHoursParser { } } - public static void parseRuleV2(String r, List rules) { - r = r.toLowerCase(); + public static void parseRuleV2(String r, int sequenceIndex, List rules) { + String comment = null; + int q1Index = r.indexOf('"'); + if (q1Index >= 0) { + int q2Index = r.indexOf('"', q1Index + 1); + if (q2Index >= 0) { + comment = r.substring(q1Index + 1, q2Index); + String a = r.substring(0, q1Index); + String b = ""; + if (r.length() > q2Index + 1) { + b = r.substring(q2Index + 1); + } + r = a + b; + } + } + r = r.toLowerCase().trim(); final String[] daysStr = new String[]{"mo", "tu", "we", "th", "fr", "sa", "su"}; final String[] monthsStr = new String[]{"jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"}; @@ -1198,7 +1438,8 @@ public class OpeningHoursParser { r = r.replace(')', ' '); String localRuleString = r.replaceAll("sunset", sunset).replaceAll("sunrise", sunrise) .replaceAll("\\+", "-" + endOfDay); - BasicOpeningHourRule basic = new BasicOpeningHourRule(); + BasicOpeningHourRule basic = new BasicOpeningHourRule(sequenceIndex); + basic.setComment(comment); boolean[] days = basic.getDays(); boolean[] months = basic.getMonths(); boolean[] dayMonths = basic.getDayMonths(); @@ -1211,32 +1452,32 @@ public class OpeningHoursParser { } List tokens = new ArrayList<>(); int startWord = 0; - for(int i = 0; i <= localRuleString.length(); i++) { + for (int i = 0; i <= localRuleString.length(); i++) { char ch = i == localRuleString.length() ? ' ' : localRuleString.charAt(i); boolean delimiter = false; Token del = null; - if(Character.isWhitespace(ch)) { + if (Character.isWhitespace(ch)) { delimiter = true; - } else if(ch == ':') { + } else if (ch == ':') { del = new Token(TokenType.TOKEN_COLON, ":"); - } else if(ch == '-') { + } else if (ch == '-') { del = new Token(TokenType.TOKEN_DASH, "-"); - } else if(ch == ',') { + } else if (ch == ',') { del = new Token(TokenType.TOKEN_COMMA, ","); } - if(delimiter || del != null) { + if (delimiter || del != null) { String wrd = localRuleString.substring(startWord, i).trim(); if(wrd.length() > 0) { tokens.add(new Token(TokenType.TOKEN_UNKNOWN, wrd)); } startWord = i + 1; - if(del != null) { + if (del != null) { tokens.add(del); } } } // recognize day of week - for(Token t : tokens) { + for (Token t : tokens) { if(t.type == TokenType.TOKEN_UNKNOWN) { findInArray(t, daysStr, TokenType.TOKEN_DAY_WEEK); } @@ -1360,7 +1601,9 @@ public class OpeningHoursParser { currentParse = t.type; } } else if (t.type.ord() < currentParse.ord() && indexP == 0 && tokens.size() > i) { - buildRule(new BasicOpeningHourRule(), tokens.subList(i, tokens.size()), rules); + BasicOpeningHourRule newRule = new BasicOpeningHourRule(basic.getSequenceIndex()); + newRule.setComment(basic.getComment()); + buildRule(newRule, tokens.subList(i, tokens.size()), rules); tokens = tokens.subList(0, i + 1); } else if (t.type == TokenType.TOKEN_COMMA) { if (tokens.size() > i + 1 && tokens.get(i + 1) != null && tokens.get(i + 1).type.ord() < currentParse.ord()) { @@ -1405,14 +1648,55 @@ public class OpeningHoursParser { } } + private static List> splitSequences(String format) { + if (format == null) { + return null; + } + List> res = new ArrayList<>(); + String[] sequences = format.split("\\|\\|"); + for (String seq : sequences) { + seq = seq.trim(); + if (seq.length() == 0) { + continue; + } + + List rules = new ArrayList<>(); + boolean comment = false; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < seq.length(); i++) { + char c = seq.charAt(i); + if (c == '"') { + comment = !comment; + sb.append(c); + } else if (c == ';' && !comment) { + if (sb.length() > 0) { + String s = sb.toString().trim(); + if (s.length() > 0) { + rules.add(s); + } + sb.setLength(0); + } + } else { + sb.append(c); + } + } + if (sb.length() > 0) { + rules.add(sb.toString()); + sb.setLength(0); + } + res.add(rules); + } + return res; + } + /** * Parse an opening_hours string from OSM to an OpeningHours object which can be used to check * * @param r the string to parse * @return BasicRule if the String is successfully parsed and UnparseableRule otherwise */ - public static void parseRules(String r, List rules) { - parseRuleV2(r, rules); + public static void parseRules(String r, int sequenceIndex, List rules) { + parseRuleV2(r, sequenceIndex, rules); } /** @@ -1425,25 +1709,38 @@ public class OpeningHoursParser { if (format == null) { return null; } - // split the OSM string in multiple rules - String[] rules = format.split(";"); //$NON-NLS-1$ - // FIXME: What if the semicolon is inside a quoted string? OpeningHours rs = new OpeningHours(); rs.setOriginal(format); - for (String r : rules) { - r = r.trim(); - if (r.length() == 0) { - continue; - } - // check if valid - List rList = new ArrayList<>(); - parseRules(r, rList); - for (OpeningHoursParser.OpeningHoursRule rule : rList) { - if (rule instanceof BasicOpeningHourRule) { - rs.addRule(rule); + // split the OSM string in multiple rules + List> sequences = splitSequences(format); + for (int i = 0; i < sequences.size(); i++) { + List rules = sequences.get(i); + List basicRules = new ArrayList<>(); + for (String r : rules) { + // check if valid + List rList = new ArrayList<>(); + parseRules(r, i, rList); + for (OpeningHoursRule rule : rList) { + if (rule instanceof BasicOpeningHourRule) { + basicRules.add((BasicOpeningHourRule) rule); + } } } + String basicRuleComment = null; + for (BasicOpeningHourRule bRule : basicRules) { + if (!Algorithms.isEmpty(bRule.getComment())) { + basicRuleComment = bRule.getComment(); + break; + } + } + if (!Algorithms.isEmpty(basicRuleComment)) { + for (BasicOpeningHourRule bRule : basicRules) { + bRule.setComment(basicRuleComment); + } + } + rs.addRules(basicRules); } + rs.setSequenceCount(sequences.size()); return rs; } @@ -1459,22 +1756,35 @@ public class OpeningHoursParser { if (format == null) { return null; } - String[] rules = format.split(";"); //$NON-NLS-1$ OpeningHoursParser.OpeningHours rs = new OpeningHoursParser.OpeningHours(); rs.setOriginal(format); - for (String r : rules) { - r = r.trim(); - if (r.length() == 0) { - continue; + List> sequences = splitSequences(format); + for (int i = sequences.size() - 1; i >= 0; i--) { + List rules = sequences.get(i); + for (String r : rules) { + r = r.trim(); + if (r.length() == 0) { + continue; + } + // check if valid + List rList = new ArrayList<>(); + parseRules(r, i, rList); + rs.addRules(rList); } - // check if valid - List rList = new ArrayList<>(); - parseRules(r, rList); - rs.addRules(rList); } + rs.setSequenceCount(sequences.size()); return rs; } + public static List getInfo(String format) { + OpeningHours openingHours = OpeningHoursParser.parseOpenedHours(format); + if (openingHours == null) { + return null; + } else { + return openingHours.getInfo(); + } + } + private static void formatTime(int h, int t, StringBuilder b) { if (h < 10) { b.append("0"); //$NON-NLS-1$ @@ -1502,9 +1812,9 @@ public class OpeningHoursParser { private static void testOpened(String time, OpeningHours hours, boolean expected) throws ParseException { Calendar cal = Calendar.getInstance(); cal.setTime(new SimpleDateFormat("dd.MM.yyyy HH:mm", Locale.US).parse(time)); - boolean calculated = hours.isOpenedForTimeV2(cal); + boolean calculated = hours.isOpenedForTimeV2(cal, OpeningHours.ALL_SEQUENCES); System.out.printf(" %sok: Expected %s: %b = %b (rule %s)\n", - ((calculated != expected) ? "NOT " : ""), time, expected, calculated, hours.getCurrentRuleTime(cal)); + ((calculated != expected) ? "NOT " : ""), time, expected, calculated, hours.getCurrentRuleTime(cal, OpeningHours.ALL_SEQUENCES)); if (calculated != expected) { throw new IllegalArgumentException("BUG!!!"); } @@ -1521,50 +1831,49 @@ public class OpeningHoursParser { * "Open till HH:mm" - close in 5 hours * "Will close at HH:mm" - close in 2 hours * "Will open on HH:mm (Mo,Tu,We,Th,Fr,Sa,Su)" - open in >5 hours + * "Will open tomorrow at HH:mm" - open in >5 hours tomorrow * "Open 24/7" - open 24/7 */ private static void testInfo(String time, OpeningHours hours, String expected) throws ParseException + { + testInfo(time, hours, expected, OpeningHours.ALL_SEQUENCES); + } + + /** + * test if the calculated opening hours are what you expect + * + * @param time the time to test in the format "dd.MM.yyyy HH:mm" + * @param hours the OpeningHours object + * @param expected the expected string in format: + * "Open from HH:mm" - open in 5 hours + * "Will open at HH:mm" - open in 2 hours + * "Open till HH:mm" - close in 5 hours + * "Will close at HH:mm" - close in 2 hours + * "Will open on HH:mm (Mo,Tu,We,Th,Fr,Sa,Su)" - open in >5 hours + * "Will open tomorrow at HH:mm" - open in >5 hours tomorrow + * "Open 24/7" - open 24/7 + * @param sequenceIndex sequence index of rules separated by || + */ + private static void testInfo(String time, OpeningHours hours, String expected, int sequenceIndex) throws ParseException { Calendar cal = Calendar.getInstance(); cal.setTime(new SimpleDateFormat("dd.MM.yyyy HH:mm", Locale.US).parse(time)); - - boolean opened24_calc = false; - boolean openFrom_calc = false; - boolean willOpenAt_calc = false; - boolean openTill_calc = false; - boolean willCloseAt_calc = false; - boolean willOpenOn_calc = false; - - boolean opened = hours.isOpenedForTimeV2(cal); - if (opened) { - opened24_calc = hours.isOpened24_7(); - openTill_calc = !Algorithms.isEmpty(hours.getClosingTime(cal)); - willCloseAt_calc = !Algorithms.isEmpty(hours.getNearToClosingTime(cal)); - } else { - openFrom_calc = !Algorithms.isEmpty(hours.getOpeningTime(cal)); - willOpenAt_calc = !Algorithms.isEmpty(hours.getNearToOpeningTime(cal)); - willOpenOn_calc = !Algorithms.isEmpty(hours.getOpeningDay(cal)); - } - - String description = "Unknown"; - if (opened24_calc) { - description = "Open 24/7"; - } else if (willOpenAt_calc) { - description = "Will open at " + hours.getNearToOpeningTime(cal); - } else if (openFrom_calc) { - description = "Open from " + hours.getOpeningTime(cal); - } else if (willCloseAt_calc) { - description = "Will close at " + hours.getNearToClosingTime(cal); - } else if (openTill_calc) { - description = "Open till " + hours.getClosingTime(cal); - } else if (willOpenOn_calc) { - description = "Will open on " + hours.getOpeningDay(cal); - } - - boolean result = expected.equalsIgnoreCase(description); - + + String description; + boolean result; + if (sequenceIndex == OpeningHours.ALL_SEQUENCES) { + OpeningHours.Info info = hours.getCombinedInfo(cal); + description = info.getInfo(); + result = expected.equalsIgnoreCase(description); + } else { + List infos = hours.getInfo(cal); + OpeningHours.Info info = infos.get(sequenceIndex); + description = info.getInfo(); + result = expected.equalsIgnoreCase(description); + } + System.out.printf(" %sok: Expected %s (%s): %s (rule %s)\n", - (!result ? "NOT " : ""), time, expected, description, hours.getCurrentRuleTime(cal)); + (!result ? "NOT " : ""), time, expected, description, hours.getCurrentRuleTime(cal, sequenceIndex)); if (!result) throw new IllegalArgumentException("BUG!!!"); @@ -1584,22 +1893,15 @@ public class OpeningHoursParser { // 0. not supported MON DAY-MON DAY (only supported Feb 2-14 or Feb-Oct: 09:00-17:30) // parseOpenedHours("Feb 16-Oct 15: 09:00-18:30; Oct 16-Nov 15: 09:00-17:30; Nov 16-Feb 15: 09:00-16:30"); - // 1. not supported (,) - // hours = parseOpenedHours("Mo-Su 07:00-23:00, Fr 08:00-20:00"); - - // 2. not supported break properly - // parseOpenedHours("Sa-Su 10:00-17:00 || \"by appointment\""); - // comment is dropped - - // 3. not properly supported + // 1. not properly supported // hours = parseOpenedHours("Mo-Su (sunrise-00:30)-(sunset+00:30)"); - // Test basic case + // test basic case OpeningHours hours = parseOpenedHours("Mo-Fr 08:30-14:40"); //$NON-NLS-1$ + System.out.println(hours); testOpened("09.08.2012 11:00", hours, true); testOpened("09.08.2012 16:00", hours, false); hours = parseOpenedHours("mo-fr 07:00-19:00; sa 12:00-18:00"); - System.out.println(hours); String string = "Mo-Fr 11:30-15:00, 17:30-23:00; Sa, Su, PH 11:30-23:00"; hours = parseOpenedHours(string); @@ -1793,11 +2095,11 @@ public class OpeningHoursParser { testInfo("15.01.2018 13:10", hours, "Will open at 14:00"); testInfo("15.01.2018 14:00", hours, "Open till 18:00"); testInfo("15.01.2018 16:00", hours, "Will close at 18:00"); - testInfo("15.01.2018 18:10", hours, "Will open on 09:00 Tu"); + testInfo("15.01.2018 18:10", hours, "Will open tomorrow at 09:00"); hours = parseOpenedHours("Mo-Sa 02:00-10:00; Th off"); System.out.println(hours); - testInfo("15.01.2018 23:00", hours, "Will open on 02:00 Tu"); + testInfo("15.01.2018 23:00", hours, "Will open tomorrow at 02:00"); hours = parseOpenedHours("Mo-Sa 23:00-02:00; Th off"); System.out.println(hours); @@ -1808,10 +2110,10 @@ public class OpeningHoursParser { hours = parseOpenedHours("Mo-Sa 08:30-17:00; Th off"); System.out.println(hours); - testInfo("17.01.2018 20:00", hours, "Will open on 08:30 Fr"); - testInfo("18.01.2018 05:00", hours, "Will open on 08:30 Fr"); + testInfo("17.01.2018 20:00", hours, "Will open on 08:30 Fr."); + testInfo("18.01.2018 05:00", hours, "Will open tomorrow at 08:30"); testInfo("20.01.2018 05:00", hours, "Open from 08:30"); - testInfo("21.01.2018 05:00", hours, "Will open on 08:30 Mo"); + testInfo("21.01.2018 05:00", hours, "Will open tomorrow at 08:30"); testInfo("22.01.2018 02:00", hours, "Open from 08:30"); testInfo("22.01.2018 04:00", hours, "Open from 08:30"); testInfo("22.01.2018 07:00", hours, "Will open at 08:30"); @@ -1830,6 +2132,31 @@ public class OpeningHoursParser { testOpened("19.01.2018 07:45", hours, false); testOpened("19.01.2018 08:45", hours, true); testOpened("19.01.2018 20:45", hours, false); - + + // test fallback case + hours = parseOpenedHours("07:00-01:00 open \"Restaurant\" || Mo 00:00-04:00,07:00-04:00; Tu-Th 07:00-04:00; Fr 07:00-24:00; Sa,Su 00:00-24:00 open \"McDrive\""); + System.out.println(hours); + testOpened("22.01.2018 00:30", hours, true); + testOpened("22.01.2018 08:00", hours, true); + testOpened("22.01.2018 03:30", hours, true); + testOpened("22.01.2018 05:00", hours, false); + testOpened("23.01.2018 05:00", hours, false); + testOpened("27.01.2018 05:00", hours, true); + testOpened("28.01.2018 05:00", hours, true); + + testInfo("22.01.2018 05:00", hours, "Will open at 07:00 (Restaurant)", 0); + testInfo("26.01.2018 00:00", hours, "Will close at 01:00 (Restaurant)", 0); + testInfo("22.01.2018 05:00", hours, "Will open at 07:00 (McDrive)", 1); + testInfo("22.01.2018 00:00", hours, "Open till 04:00 (McDrive)", 1); + testInfo("22.01.2018 02:00", hours, "Will close at 04:00 (McDrive)", 1); + testInfo("27.01.2018 02:00", hours, "Open till 24:00 (McDrive)", 1); + + hours = parseOpenedHours("07:00-03:00 open \"Restaurant\" || 24/7 open \"McDrive\""); + System.out.println(hours); + testOpened("22.01.2018 02:00", hours, true); + testOpened("22.01.2018 17:00", hours, true); + testInfo("22.01.2018 05:00", hours, "Will open at 07:00 (Restaurant)", 0); + testInfo("22.01.2018 04:00", hours, "Open 24/7 (McDrive)", 1); + } } diff --git a/OsmAnd/res/layout/map_context_menu_fragment.xml b/OsmAnd/res/layout/map_context_menu_fragment.xml index 4306395700..8117d56a8a 100644 --- a/OsmAnd/res/layout/map_context_menu_fragment.xml +++ b/OsmAnd/res/layout/map_context_menu_fragment.xml @@ -1,12 +1,12 @@ + android:background="@android:color/transparent"> + android:paddingRight="@dimen/context_menu_padding_margin_default"> + android:text="@string/search_address_building"/> + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/context_menu_subtitle_margin"> + android:text="@string/amenity_type_finance"/> @@ -80,40 +80,42 @@ android:columnWidth="@dimen/context_menu_transport_grid_item_width" android:horizontalSpacing="@dimen/context_menu_transport_grid_spacing" android:numColumns="auto_fit" + android:paddingBottom="@dimen/context_menu_transport_grid_spacing" android:paddingLeft="@dimen/context_menu_padding_margin_default" android:paddingRight="@dimen/context_menu_padding_margin_default" android:paddingTop="@dimen/context_menu_transport_padding_top" - android:paddingBottom="@dimen/context_menu_transport_grid_spacing" android:verticalSpacing="@dimen/context_menu_transport_grid_spacing" android:visibility="gone"/> + android:layout_height= "wrap_content" + android:layout_marginBottom="@dimen/context_menu_direction_margin" + android:layout_marginTop="@dimen/context_menu_padding_margin_tiny" + android:gravity="center_vertical" + android:orientation="horizontal" + android:paddingTop="3dp" + android:paddingBottom="3dp" + android:paddingLeft="@dimen/context_menu_padding_margin_default" + android:paddingRight="@dimen/context_menu_padding_margin_default"> + tools:text="Museum"/> + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/context_menu_padding_margin_small" + android:layout_marginRight="@dimen/context_menu_padding_margin_small" + tools:text="Closed till 10:00"/> + tools:src="@drawable/ic_direction_arrow"/> + tools:text="100500 km" + tools:textColor="?android:textColorSecondary"/> @@ -155,17 +157,16 @@ tools:visibility="visible"> + android:orientation="horizontal" + tools:background="?attr/ctx_menu_controller_bg"> + android:textAllCaps="true" + android:textSize="@dimen/default_desc_text_size" + osmand:typeface="@string/font_roboto_medium" + tools:textColor="?attr/ctx_menu_controller_text_color"/> + android:orientation="horizontal" + tools:background="?attr/ctx_menu_controller_bg"> + android:textAllCaps="true" + android:textSize="@dimen/default_desc_text_size" + osmand:typeface="@string/font_roboto_medium" + tools:textColor="?attr/ctx_menu_controller_text_color"/> @@ -229,16 +231,14 @@ + tools:background="?attr/ctx_menu_controller_bg"> + android:textAllCaps="true" + android:textSize="@dimen/default_desc_text_size" + osmand:typeface="@string/font_roboto_medium" + tools:textColor="?attr/ctx_menu_controller_text_color"/> + tools:background="?attr/ctx_menu_controller_bg"> + android:textAllCaps="true" + android:textSize="@dimen/default_desc_text_size" + osmand:typeface="@string/font_roboto_medium" + tools:textColor="?attr/ctx_menu_controller_text_color"/> @@ -308,9 +310,9 @@ android:paddingRight="@dimen/context_menu_button_padding_x" android:text="@string/shared_string_delete" android:textAllCaps="true" - tools:textColor="?attr/ctx_menu_controller_text_color" android:textSize="@dimen/default_desc_text_size" - osmand:typeface="@string/font_roboto_medium"/> + osmand:typeface="@string/font_roboto_medium" + tools:textColor="?attr/ctx_menu_controller_text_color"/> @@ -325,10 +327,10 @@ android:minHeight="@dimen/context_menu_action_buttons_h" android:orientation="horizontal" android:paddingBottom="@dimen/context_menu_padding_margin_small" - android:paddingLeft="@dimen/context_menu_progress_padding_left" - android:paddingStart="@dimen/context_menu_progress_padding_left" - android:paddingRight="@dimen/context_menu_progress_padding_right" android:paddingEnd="@dimen/context_menu_progress_padding_right" + android:paddingLeft="@dimen/context_menu_progress_padding_left" + android:paddingRight="@dimen/context_menu_progress_padding_right" + android:paddingStart="@dimen/context_menu_progress_padding_left" android:visibility="gone" tools:visibility="visible"> @@ -364,11 +366,11 @@ @@ -383,73 +385,73 @@ android:background="?attr/ctx_menu_divider"/> + android:orientation="horizontal" + android:paddingLeft="@dimen/map_widget_icon_margin" + android:paddingRight="@dimen/map_widget_icon_margin"> + android:paddingBottom="@dimen/context_menu_main_actions_padding_bottom" + android:paddingTop="@dimen/context_menu_main_actions_padding_top"> + osmand:typeface="@string/font_roboto_regular" + tools:text="@string/shared_string_add"/> + android:paddingBottom="@dimen/context_menu_main_actions_padding_bottom" + android:paddingTop="@dimen/context_menu_main_actions_padding_top"> + android:paddingBottom="@dimen/context_menu_main_actions_padding_bottom" + android:paddingTop="@dimen/context_menu_main_actions_padding_top"> + android:paddingBottom="@dimen/context_menu_main_actions_padding_bottom" + android:paddingTop="@dimen/context_menu_main_actions_padding_top"> + tools:textColor="?attr/contextMenuButtonColor"/> + tools:textColor="?attr/contextMenuButtonColor"/> @@ -589,8 +591,8 @@ android:id="@+id/context_menu_bottom_view" android:layout_width="match_parent" android:layout_height="wrap_content" - tools:background="?attr/ctx_menu_info_view_bg" - android:orientation="vertical"> + android:orientation="vertical" + tools:background="?attr/ctx_menu_info_view_bg"> @@ -610,8 +612,8 @@ android:layout_width="@dimen/fab_size_with_shadow" android:layout_height="wrap_content" android:layout_gravity="right" - android:gravity="center" android:layout_marginRight="@dimen/fab_margin_right" + android:gravity="center" android:orientation="vertical" android:visibility="gone" tools:visibility="visible"> diff --git a/OsmAnd/res/values/strings.xml b/OsmAnd/res/values/strings.xml index b7a71054b4..43a84e03c8 100644 --- a/OsmAnd/res/values/strings.xml +++ b/OsmAnd/res/values/strings.xml @@ -9,6 +9,7 @@ 3. All your modified/created strings are in the top of the file (to make easier find what\'s translated). PLEASE: Have a look at http://code.google.com/p/osmand/wiki/UIConsistency, it may really improve your and our work :-) Thx - Hardy --> + Will open tomorrow at POI labels Without name What\'s here: diff --git a/OsmAnd/src/net/osmand/plus/AppInitializer.java b/OsmAnd/src/net/osmand/plus/AppInitializer.java index b988c7523f..4a0b65cc15 100644 --- a/OsmAnd/src/net/osmand/plus/AppInitializer.java +++ b/OsmAnd/src/net/osmand/plus/AppInitializer.java @@ -47,6 +47,7 @@ import net.osmand.plus.voice.TTSCommandPlayerImpl; import net.osmand.render.RenderingRulesStorage; import net.osmand.router.RoutingConfiguration; import net.osmand.util.Algorithms; +import net.osmand.util.OpeningHoursParser; import org.xmlpull.v1.XmlPullParserException; @@ -378,8 +379,21 @@ public class AppInitializer implements IProgress { app.mapMarkersDbHelper = startupInit(new MapMarkersDbHelper(app), MapMarkersDbHelper.class); app.mapMarkersHelper = startupInit(new MapMarkersHelper(app), MapMarkersHelper.class); app.searchUICore = startupInit(new QuickSearchHelper(app), QuickSearchHelper.class); + + initOpeningHoursParser(); } + private void initOpeningHoursParser() { + OpeningHoursParser.setAdditionalString("off", app.getString(R.string.day_off_label)); + OpeningHoursParser.setAdditionalString("is_open", app.getString(R.string.poi_dialog_opening_hours)); + OpeningHoursParser.setAdditionalString("is_open_24_7", app.getString(R.string.shared_string_is_open_24_7)); + OpeningHoursParser.setAdditionalString("will_open_at", app.getString(R.string.will_open_at)); + OpeningHoursParser.setAdditionalString("open_from", app.getString(R.string.open_from)); + OpeningHoursParser.setAdditionalString("will_close_at", app.getString(R.string.will_close_at)); + OpeningHoursParser.setAdditionalString("open_till", app.getString(R.string.open_till)); + OpeningHoursParser.setAdditionalString("will_open_tomorrow_at", app.getString(R.string.will_open_tomorrow_at)); + OpeningHoursParser.setAdditionalString("will_open_on", app.getString(R.string.will_open_on)); + } private void updateRegionVars() { app.regions.setTranslator(new RegionTranslation() { diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenu.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenu.java index 8d2bc0c919..6638225c95 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenu.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenu.java @@ -1175,7 +1175,7 @@ public class MapContextMenu extends MenuTitleController implements StateChangedL return 0; } - public String getAdditionalInfo() { + public CharSequence getAdditionalInfo() { if (menuController != null) { return menuController.getAdditionalInfoStr(); } diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java index a224be9ab5..2992b6b4bf 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MapContextMenuFragment.java @@ -1196,7 +1196,7 @@ public class MapContextMenuFragment extends BaseOsmAndFragment implements Downlo } TextView additionalInfoTextView = (TextView) view.findViewById(R.id.additional_info_text_view); - String additionalInfoStr = menu.getAdditionalInfo(); + CharSequence additionalInfoStr = menu.getAdditionalInfo(); if (!TextUtils.isEmpty(additionalInfoStr)) { int colorId = menu.getAdditionalInfoColor(); int additionalInfoIconRes = menu.getAdditionalInfoIconRes(); diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuController.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuController.java index c02974f397..9491e2daec 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuController.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/MenuController.java @@ -8,6 +8,8 @@ import android.support.annotation.DrawableRes; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; +import android.text.SpannableString; +import android.text.style.ForegroundColorSpan; import android.view.View; import android.view.View.OnClickListener; import android.widget.LinearLayout; @@ -29,9 +31,7 @@ import net.osmand.map.WorldRegion; import net.osmand.plus.GPXUtilities.WptPt; import net.osmand.plus.GpxSelectionHelper.GpxDisplayItem; import net.osmand.plus.MapMarkersHelper.MapMarker; -import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandPlugin; -import net.osmand.plus.OsmandSettings; import net.osmand.plus.R; import net.osmand.plus.TargetPointsHelper.TargetPoint; import net.osmand.plus.activities.MapActivity; @@ -74,6 +74,7 @@ import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarControll import net.osmand.plus.views.mapwidgets.MapInfoWidgetsFactory.TopToolbarControllerType; import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; +import net.osmand.util.OpeningHoursParser.OpeningHours; import java.io.IOException; import java.util.Iterator; @@ -117,6 +118,8 @@ public abstract class MenuController extends BaseMenuController { private WorldRegion downloadRegion; private DownloadIndexesThread downloadThread; + protected List openingHoursInfo; + public MenuController(MenuBuilder builder, PointDescription pointDescription, MapActivity mapActivity) { super(mapActivity); this.pointDescription = pointDescription; @@ -243,12 +246,8 @@ public abstract class MenuController extends BaseMenuController { } protected void addMyLocationToPlainItems(LatLon latLon) { - OsmandSettings st = ((OsmandApplication) getMapActivity().getApplicationContext()).getSettings(); addPlainMenuItem(R.drawable.ic_action_get_my_location, null, PointDescription.getLocationName(getMapActivity(), latLon.getLatitude(), latLon.getLongitude(), true).replaceAll("\n", " "), false, false, null); - //if (st.COORDINATES_FORMAT.get() != PointDescription.OLC_FORMAT) - // addPlainMenuItem(R.drawable.ic_action_get_my_location, PointDescription.getLocationOlcName( - // latLon.getLatitude(), latLon.getLongitude()).replaceAll("\n", " "), false, false, null); } public PointDescription getPointDescription() { @@ -442,21 +441,47 @@ public abstract class MenuController extends BaseMenuController { } public int getAdditionalInfoColor() { - if (indexItem != null) { + if (openingHoursInfo != null) { + return 0; + } else if (indexItem != null) { return R.color.icon_color; } return 0; } - public String getAdditionalInfoStr() { - if (indexItem != null) { + public CharSequence getAdditionalInfoStr() { + if (openingHoursInfo != null) { + StringBuilder sb = new StringBuilder(); + int colorOpen = getMapActivity().getResources().getColor(R.color.ctx_menu_amenity_opened_text_color); + int colorClosed = getMapActivity().getResources().getColor(R.color.ctx_menu_amenity_closed_text_color); + int[] pos = new int[openingHoursInfo.size()]; + for (int i = 0; i < openingHoursInfo.size(); i++) { + OpeningHours.Info info = openingHoursInfo.get(i); + if (sb.length() > 0) { + sb.append("\n"); + } + sb.append(info.getInfo()); + pos[i] = sb.length(); + } + SpannableString infoStr = new SpannableString(sb.toString()); + int k = 0; + for (int i = 0; i < openingHoursInfo.size(); i++) { + OpeningHours.Info info = openingHoursInfo.get(i); + infoStr.setSpan(new ForegroundColorSpan(info.isOpened() ? colorOpen : colorClosed), k, pos[i], 0); + k = pos[i]; + } + return infoStr; + + } else if (indexItem != null) { return getMapActivity().getString(R.string.file_size_in_mb, indexItem.getArchiveSizeMB()); } return ""; } public int getAdditionalInfoIconRes() { - if (indexItem != null) { + if (openingHoursInfo != null) { + return R.drawable.ic_action_opening_hour_16; + } else if (indexItem != null) { return R.drawable.ic_sdcard_16; } return 0; diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/OpeningHoursInfo.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/OpeningHoursInfo.java deleted file mode 100644 index 34990e86ac..0000000000 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/OpeningHoursInfo.java +++ /dev/null @@ -1,90 +0,0 @@ -package net.osmand.plus.mapcontextmenu; - -import android.content.Context; - -import net.osmand.plus.R; -import net.osmand.util.Algorithms; - -public class OpeningHoursInfo { - - private boolean opened; - private boolean opened24_7; - private String openingTime = ""; - private String nearToOpeningTime = ""; - private String closingTime = ""; - private String nearToClosingTime = ""; - private String openingDay = ""; - - public boolean isOpened() { - return opened; - } - - public void setOpened(boolean opened) { - this.opened = opened; - } - - public boolean isOpened24_7() { - return opened24_7; - } - - public void setOpened24_7(boolean opened24_7) { - this.opened24_7 = opened24_7; - } - - public String getOpeningTime() { - return openingTime; - } - - public void setOpeningTime(String openFromTime) { - this.openingTime = openFromTime; - } - - public String getNearToOpeningTime() { - return nearToOpeningTime; - } - - public void setNearToOpeningTime(String nearToOpeningTime) { - this.nearToOpeningTime = nearToOpeningTime; - } - - public String getClosingTime() { - return closingTime; - } - - public void setClosingTime(String closingTime) { - this.closingTime = closingTime; - } - - public String getNearToClosingTime() { - return nearToClosingTime; - } - - public void setNearToClosingTime(String nearToClosingTime) { - this.nearToClosingTime = nearToClosingTime; - } - - public String getOpeningDay() { - return openingDay; - } - - public void setOpeningDay(String openingDay) { - this.openingDay = openingDay; - } - - public String getInfo(Context context) { - if (isOpened24_7()) { - return context.getString(R.string.shared_string_is_open_24_7); - } else if (!Algorithms.isEmpty(getNearToOpeningTime())) { - return context.getString(R.string.will_open_at) + " " + getNearToOpeningTime(); - } else if (!Algorithms.isEmpty(getOpeningTime())) { - return context.getString(R.string.open_from) + " " + getOpeningTime(); - } else if (!Algorithms.isEmpty(getNearToClosingTime())) { - return context.getString(R.string.will_close_at) + " " + getNearToClosingTime(); - } else if (!Algorithms.isEmpty(getClosingTime())) { - return context.getString(R.string.open_till) + " " + getClosingTime(); - } else if (!Algorithms.isEmpty(getOpeningDay())) { - return context.getString(R.string.will_open_on) + " " + getOpeningDay() + "."; - } - return ""; - } -} diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/AmenityMenuBuilder.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/AmenityMenuBuilder.java index bdbcfe2335..19d176fe5f 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/AmenityMenuBuilder.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/AmenityMenuBuilder.java @@ -529,11 +529,6 @@ public class AmenityMenuBuilder extends MenuBuilder { buildRow(view, R.drawable.ic_action_get_my_location, null, PointDescription.getLocationName(app, amenity.getLocation().getLatitude(), amenity.getLocation().getLongitude(), true) .replaceAll("\n", " "), 0, false, null, false, 0, false, null, false); - //if (st.COORDINATES_FORMAT.get() != PointDescription.OLC_FORMAT) - // buildRow(view, R.drawable.ic_action_get_my_location, PointDescription.getLocationOlcName( - // amenity.getLocation().getLatitude(), amenity.getLocation().getLongitude()) - // .replaceAll("\n", " "), 0, false, null, false, 0, false, null); - } public void buildAmenityRow(View view, AmenityInfoRow info) { diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/FavouritePointMenuBuilder.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/FavouritePointMenuBuilder.java index 55056d5279..7afcdf4d41 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/FavouritePointMenuBuilder.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/builders/FavouritePointMenuBuilder.java @@ -1,17 +1,12 @@ package net.osmand.plus.mapcontextmenu.builders; import android.graphics.Color; -import android.text.TextUtils; -import android.view.Gravity; import android.view.View; -import android.widget.LinearLayout; import net.osmand.ResultMatcher; import net.osmand.binary.BinaryMapIndexReader; import net.osmand.data.Amenity; import net.osmand.data.FavouritePoint; -import net.osmand.data.LatLon; -import net.osmand.data.PointDescription; import net.osmand.data.QuadRect; import net.osmand.data.TransportStop; import net.osmand.osm.PoiCategory; @@ -19,7 +14,6 @@ import net.osmand.plus.FavouritesDbHelper.FavoriteGroup; import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.mapcontextmenu.MenuBuilder; -import net.osmand.plus.widgets.TextViewEx; import net.osmand.util.MapUtils; import java.util.List; @@ -36,7 +30,7 @@ public class FavouritePointMenuBuilder extends MenuBuilder { acquireOriginObject(); } - public void acquireOriginObject() + private void acquireOriginObject() { String originObjectName = fav.getOriginObjectName(); if (originObjectName.length() > 0) { diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/AmenityMenuController.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/AmenityMenuController.java index 62102af5c3..3f886a4c2b 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/AmenityMenuController.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/AmenityMenuController.java @@ -14,19 +14,17 @@ import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.mapcontextmenu.MenuBuilder; import net.osmand.plus.mapcontextmenu.MenuController; -import net.osmand.plus.mapcontextmenu.OpeningHoursInfo; import net.osmand.plus.mapcontextmenu.WikipediaDialogFragment; import net.osmand.plus.mapcontextmenu.builders.AmenityMenuBuilder; -import net.osmand.plus.transport.TransportStopRoute; import net.osmand.plus.render.RenderingIcons; import net.osmand.plus.resources.TransportIndexRepository; +import net.osmand.plus.transport.TransportStopRoute; import net.osmand.plus.transport.TransportStopType; import net.osmand.util.Algorithms; import net.osmand.util.MapUtils; import net.osmand.util.OpeningHoursParser; import java.util.ArrayList; -import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -36,7 +34,6 @@ public class AmenityMenuController extends MenuController { private Amenity amenity; private List routes = new ArrayList<>(); - private OpeningHoursInfo openingHoursInfo; private MapMarker marker; @@ -77,7 +74,7 @@ public class AmenityMenuController extends MenuController { leftTitleButtonController.updateStateListDrawableIcon(R.drawable.ic_action_read_text, true); } - openingHoursInfo = processOpeningHours(amenity); + openingHoursInfo = OpeningHoursParser.getInfo(amenity.getOpeningHours()); } @Override @@ -146,30 +143,6 @@ public class AmenityMenuController extends MenuController { return getTypeStr(amenity); } - @Override - public int getAdditionalInfoColor() { - if (openingHoursInfo != null) { - return openingHoursInfo.isOpened() ? R.color.ctx_menu_amenity_opened_text_color : R.color.ctx_menu_amenity_closed_text_color; - } - return super.getAdditionalInfoColor(); - } - - @Override - public String getAdditionalInfoStr() { - if (openingHoursInfo != null) { - return openingHoursInfo.getInfo(getMapActivity()); - } - return super.getAdditionalInfoStr(); - } - - @Override - public int getAdditionalInfoIconRes() { - if (openingHoursInfo != null) { - return R.drawable.ic_action_opening_hour_16; - } - return super.getAdditionalInfoIconRes(); - } - public static String getTypeStr(Amenity amenity) { PoiCategory pc = amenity.getType(); PoiType pt = pc.getPoiTypeByKeyName(amenity.getSubType()); @@ -182,28 +155,6 @@ public class AmenityMenuController extends MenuController { return typeStr; } - public static OpeningHoursInfo processOpeningHours(Amenity amenity) { - OpeningHoursParser.OpeningHours openingHours = OpeningHoursParser.parseOpenedHours(amenity.getOpeningHours()); - if (openingHours == null) { - return null; - } else { - OpeningHoursInfo info = new OpeningHoursInfo(); - Calendar cal = Calendar.getInstance(); - boolean opened = openingHours.isOpenedForTime(cal); - info.setOpened(opened); - if (opened) { - info.setOpened24_7(openingHours.isOpened24_7()); - info.setClosingTime(openingHours.getClosingTime(cal)); - info.setNearToClosingTime(openingHours.getNearToClosingTime(cal)); - } else { - info.setOpeningTime(openingHours.getOpeningTime(cal)); - info.setNearToOpeningTime(openingHours.getNearToOpeningTime(cal)); - info.setOpeningDay(openingHours.getOpeningDay(cal)); - } - return info; - } - } - @Override public String getCommonTypeStr() { PoiCategory pc = amenity.getType(); @@ -219,7 +170,8 @@ public class AmenityMenuController extends MenuController { public void addPlainMenuItems(String typeStr, PointDescription pointDescription, LatLon latLon) { } - public static void addPlainMenuItems(Amenity amenity, String typeStr, MenuBuilder builder) { + public static void addTypeMenuItem(Amenity amenity, MenuBuilder builder) { + String typeStr = getTypeStr(amenity); if (!Algorithms.isEmpty(typeStr)) { int resId = getRightIconId(amenity); if (resId == 0) { diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/FavouritePointMenuController.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/FavouritePointMenuController.java index 0e1ddda8fa..509d1312d2 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/FavouritePointMenuController.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/FavouritePointMenuController.java @@ -14,12 +14,12 @@ import net.osmand.plus.R; import net.osmand.plus.activities.MapActivity; import net.osmand.plus.base.FavoriteImageDrawable; import net.osmand.plus.mapcontextmenu.MenuController; -import net.osmand.plus.mapcontextmenu.OpeningHoursInfo; import net.osmand.plus.mapcontextmenu.builders.FavouritePointMenuBuilder; import net.osmand.plus.mapcontextmenu.editors.FavoritePointEditor; import net.osmand.plus.mapcontextmenu.editors.FavoritePointEditorFragment; import net.osmand.plus.transport.TransportStopRoute; import net.osmand.util.Algorithms; +import net.osmand.util.OpeningHoursParser; import java.util.ArrayList; import java.util.List; @@ -29,7 +29,6 @@ public class FavouritePointMenuController extends MenuController { private FavouritePoint fav; private MapMarker mapMarker; private List routes = new ArrayList<>(); - private OpeningHoursInfo openingHoursInfo; public FavouritePointMenuController(MapActivity mapActivity, PointDescription pointDescription, final FavouritePoint fav) { super(new FavouritePointMenuBuilder(mapActivity, fav), pointDescription, mapActivity); @@ -55,7 +54,7 @@ public class FavouritePointMenuController extends MenuController { Object originObject = getBuilder().getOriginObject(); if (originObject instanceof Amenity) { - openingHoursInfo = AmenityMenuController.processOpeningHours((Amenity) originObject); + openingHoursInfo = OpeningHoursParser.getInfo(((Amenity) originObject).getOpeningHours()); } } @@ -144,35 +143,10 @@ public class FavouritePointMenuController extends MenuController { Object originObject = getBuilder().getOriginObject(); if (originObject != null) { if (originObject instanceof Amenity) { - Amenity amenity = (Amenity) originObject; - AmenityMenuController.addPlainMenuItems(amenity, AmenityMenuController.getTypeStr(amenity), builder); + AmenityMenuController.addTypeMenuItem((Amenity) originObject, builder); } } else { addMyLocationToPlainItems(latLon); } } - - @Override - public int getAdditionalInfoColor() { - if (openingHoursInfo != null) { - return openingHoursInfo.isOpened() ? R.color.ctx_menu_amenity_opened_text_color : R.color.ctx_menu_amenity_closed_text_color; - } - return 0; - } - - @Override - public String getAdditionalInfoStr() { - if (openingHoursInfo != null) { - return openingHoursInfo.getInfo(getMapActivity()); - } - return ""; - } - - @Override - public int getAdditionalInfoIconRes() { - if (openingHoursInfo != null) { - return R.drawable.ic_action_opening_hour_16; - } - return 0; - } } diff --git a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/MapDataMenuController.java b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/MapDataMenuController.java index c46251e66c..5d0df3abc6 100644 --- a/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/MapDataMenuController.java +++ b/OsmAnd/src/net/osmand/plus/mapcontextmenu/controllers/MapDataMenuController.java @@ -190,7 +190,7 @@ public class MapDataMenuController extends MenuController { } @Override - public String getAdditionalInfoStr() { + public CharSequence getAdditionalInfoStr() { double mb = 0; if (backuped) { if (localIndexInfo != null) { diff --git a/OsmAnd/src/net/osmand/plus/osmedit/EditPOIMenuController.java b/OsmAnd/src/net/osmand/plus/osmedit/EditPOIMenuController.java index 7d0d3b90e2..ac09ec8ebc 100644 --- a/OsmAnd/src/net/osmand/plus/osmedit/EditPOIMenuController.java +++ b/OsmAnd/src/net/osmand/plus/osmedit/EditPOIMenuController.java @@ -131,7 +131,7 @@ public class EditPOIMenuController extends MenuController { } @Override - public String getAdditionalInfoStr() { + public CharSequence getAdditionalInfoStr() { return actionStr; } diff --git a/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionMenuController.java b/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionMenuController.java index 440aa9905a..7d4addc480 100644 --- a/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionMenuController.java +++ b/OsmAnd/src/net/osmand/plus/parkingpoint/ParkingPositionMenuController.java @@ -68,7 +68,7 @@ public class ParkingPositionMenuController extends MenuController { } @Override - public String getAdditionalInfoStr() { + public CharSequence getAdditionalInfoStr() { return parkingLeftDescription; }