/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (props, at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.opentripplanner.graph_builder.impl.osm; import java.util.ArrayList; import java.util.List; import org.opentripplanner.common.model.P2; import org.opentripplanner.openstreetmap.model.OSMWithTags; /** Specifies a class of OSM tagged objects (e.g. ways) by a list tags and their values */ public class OSMSpecifier { public List<P2<String>> kvpairs; public OSMSpecifier() { kvpairs = new ArrayList<P2<String>>(); } public OSMSpecifier(String spec) { this(); setKvpairs(spec); } public void setKvpairs(String spec) { String[] pairs = spec.split(";"); for (String pair : pairs) { String[] kv = pair.split("="); kvpairs.add(new P2<String>(kv[0], kv[1])); } } /** * Returns a score comparing how well the parameter matches this specifier * * @param match an OSM tagged object to compare to this specifier * @return */ public P2<Integer> matchScores(OSMWithTags match) { int leftScore = 0, rightScore = 0; int leftMatches = 0, rightMatches = 0; for (P2<String> pair : kvpairs) { String tag = pair.getFirst().toLowerCase(); String value = pair.getSecond().toLowerCase(); String leftMatchValue = match.getTag(tag + ":left"); String rightMatchValue = match.getTag(tag + ":right"); String matchValue = match.getTag(tag); if (leftMatchValue == null) { leftMatchValue = matchValue; } if (rightMatchValue == null) { rightMatchValue = matchValue; } int leftTagScore = getTagScore(value, leftMatchValue); leftScore += leftTagScore; if (leftTagScore > 0) { leftMatches ++; } int rightTagScore = getTagScore(value, rightMatchValue); rightScore += rightTagScore; if (rightTagScore > 0) { rightMatches ++; } } int allMatchLeftBonus = (leftMatches == kvpairs.size()) ? 10 : 0; leftScore += allMatchLeftBonus; int allMatchRightBonus = (rightMatches == kvpairs.size()) ? 10 : 0; rightScore += allMatchRightBonus; P2<Integer> score = new P2<Integer>(leftScore, rightScore); return score; } public int matchScore(OSMWithTags match) { int score = 0; int matches = 0; for (P2<String> pair : kvpairs) { String tag = pair.getFirst().toLowerCase(); String value = pair.getSecond().toLowerCase(); String matchValue = match.getTag(tag); int tagScore = getTagScore(value, matchValue); score += tagScore; if (tagScore > 0) { matches += 1; } } score += matches == kvpairs.size() ? 10 : 0; return score; } private int getTagScore(String value, String matchValue) { // either this matches on a wildcard, or it matches exactly if (value.equals("*") && matchValue != null) { return 1; // wildcard matches are basically tiebreakers } else if (value.equals(matchValue)) { return 100; } else { if (value.contains(":")) { // treat cases like cobblestone:flattened as cobblestone if a more-specific match // does not apply value = value.split(":", 2)[0]; if (value.equals(matchValue)) { return 75; } else { return 0; } } else { return 0; } } } public void addTag(String key, String value) { kvpairs.add(new P2<String>(key, value)); } public String toString() { StringBuilder builder = new StringBuilder(); for (P2<String> pair : kvpairs) { builder.append(pair.getFirst()); builder.append("="); builder.append(pair.getSecond()); builder.append(";"); } builder.deleteCharAt(builder.length() - 1); // remove trailing semicolon return builder.toString(); } }