From bdef99c2c3c08c2e3c7968061821710cad363c14 Mon Sep 17 00:00:00 2001 From: nik Date: Thu, 17 Mar 2016 00:15:10 -0700 Subject: [PATCH] adding Brand and Model support --- src/main/java/ua_parser/Device.java | 23 ++++++-- src/main/java/ua_parser/DeviceParser.java | 72 +++++++++++++++-------- src/test/java/ua_parser/DeviceTest.java | 6 +- src/test/java/ua_parser/ParserTest.java | 4 +- 4 files changed, 70 insertions(+), 35 deletions(-) diff --git a/src/main/java/ua_parser/Device.java b/src/main/java/ua_parser/Device.java index e318ef2..a5343e1 100644 --- a/src/main/java/ua_parser/Device.java +++ b/src/main/java/ua_parser/Device.java @@ -25,13 +25,17 @@ */ public class Device { public final String family; + public final String brand; + public final String model; - public Device(String family) { + public Device(String family, String brand, String model) { this.family = family; + this.brand = brand; + this.model = model; } public static Device fromMap(Map m) { - return new Device((String) m.get("family")); + return new Device(m.get("family"), m.get("brand"), m.get("model")); } @Override @@ -40,17 +44,24 @@ public boolean equals(Object other) { if (!(other instanceof Device)) return false; Device o = (Device) other; - return (this.family != null && this.family.equals(o.family)) || this.family == o.family; + return ((this.family != null && this.family.equals(o.family)) || this.family == o.family) && + ((this.brand != null && this.brand.equals(o.brand)) || this.brand == o.brand) && + ((this.model != null && this.model.equals(o.model)) || this.model == o.model); } @Override public int hashCode() { - return family == null ? 0 : family.hashCode(); + int h = family == null ? 0 : family.hashCode(); + h += brand == null ? 0 : brand.hashCode(); + h += model == null ? 0 : model.hashCode(); + return h; } @Override public String toString() { - return String.format("{\"family\": %s}", - family == null ? Constants.EMPTY_STRING : '"' + family + '"'); + return String.format("{\"family\": %s, \"brand\": %s, \"model\": %s}", + family == null ? Constants.EMPTY_STRING : '"' + family + '"', + brand == null ? Constants.EMPTY_STRING : '"' + brand + '"', + model == null ? Constants.EMPTY_STRING : '"' + model + '"'); } } \ No newline at end of file diff --git a/src/main/java/ua_parser/DeviceParser.java b/src/main/java/ua_parser/DeviceParser.java index 868b5ba..99449e4 100644 --- a/src/main/java/ua_parser/DeviceParser.java +++ b/src/main/java/ua_parser/DeviceParser.java @@ -17,6 +17,7 @@ package ua_parser; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; @@ -39,15 +40,19 @@ public Device parse(String agentString) { return null; } - String device = null; + Map replacements = null; for (DevicePattern p : patterns) { - if ((device = p.match(agentString)) != null) { + if ((replacements = p.match(agentString)) != null) { break; } } - if (device == null) device = "Other"; - return new Device(device); + if (replacements == null) { + return new Device("Other", null, null); + } + else { + return new Device(replacements.get("device_replacement"), replacements.get("brand_replacement"), replacements.get("model_replacement")); + } } public static DeviceParser fromList(List> configList) { @@ -65,47 +70,64 @@ protected static DevicePattern patternFromMap(Map configMap) { } Pattern pattern = "i".equals(configMap.get("regex_flag")) // no ohter flags used (by now) ? Pattern.compile(regex, Pattern.CASE_INSENSITIVE) : Pattern.compile(regex); - return new DevicePattern(pattern, configMap.get("device_replacement")); + return new DevicePattern(pattern, configMap.get("device_replacement"), configMap.get("brand_replacement"), configMap.get("model_replacement")); } protected static class DevicePattern { private static final Pattern SUBSTITUTIONS_PATTERN = Pattern.compile("\\$\\d"); private final Pattern pattern; private final String deviceReplacement; + private final String brandReplacement; + private final String modelReplacement; - public DevicePattern(Pattern pattern, String deviceReplacement) { + public DevicePattern(Pattern pattern, String deviceReplacement, String brandReplacement, String modelReplacement) { this.pattern = pattern; this.deviceReplacement = deviceReplacement; + this.brandReplacement = brandReplacement; + this.modelReplacement = modelReplacement; } - public String match(String agentString) { + public Map match(String agentString) { Matcher matcher = pattern.matcher(agentString); if (!matcher.find()) { return null; } - String device = null; - if (deviceReplacement != null) { - if (deviceReplacement.contains("$")) { - device = deviceReplacement; - for (String substitution : getSubstitutions(deviceReplacement)) { - int i = Integer.valueOf(substitution.substring(1)); - String replacement = matcher.groupCount() >= i && matcher.group(i) != null - ? Matcher.quoteReplacement(matcher.group(i)) : ""; - device = device.replaceFirst("\\" + substitution, replacement); + + Map replacements = new HashMap(); + replacements.put("device_replacement", getReplacement(deviceReplacement, matcher, 1)); + replacements.put("brand_replacement", getReplacement(brandReplacement, matcher, -1)); + replacements.put("model_replacement", getReplacement(modelReplacement, matcher, 1)); + + return replacements; + } + + private String getReplacement(String replacement, Matcher matcher, int groupNum) { + String replacementOut = null; + if (replacement != null) { + if (replacement.contains("$")) { + replacementOut = replacement; + for (String substitution : getSubstitutions(replacement)) { + int i = Integer.valueOf(substitution.substring(1)); + String replacementGroup = matcher.groupCount() >= i && matcher.group(i) != null + ? Matcher.quoteReplacement(matcher.group(i)) : ""; + replacementOut = replacementOut.replaceFirst("\\" + substitution, replacementGroup); } - device = device.trim(); - } else { - device = deviceReplacement; - } - } else if (matcher.groupCount() >= 1) { - device = matcher.group(1); + replacementOut = replacementOut.trim(); + } else { + replacementOut = replacement; + } + } else if (groupNum > 0 && matcher.groupCount() >= 1) { + replacementOut = matcher.group(groupNum); } - return device; + if(replacementOut == null || replacementOut.isEmpty()) + return null; + else + return replacementOut; } - private List getSubstitutions(String deviceReplacement) { - Matcher matcher = SUBSTITUTIONS_PATTERN.matcher(deviceReplacement); + private List getSubstitutions(String replacement) { + Matcher matcher = SUBSTITUTIONS_PATTERN.matcher(replacement); List substitutions = new ArrayList(); while (matcher.find()) { substitutions.add(matcher.group()); diff --git a/src/test/java/ua_parser/DeviceTest.java b/src/test/java/ua_parser/DeviceTest.java index 0ecfba4..1a7e643 100644 --- a/src/test/java/ua_parser/DeviceTest.java +++ b/src/test/java/ua_parser/DeviceTest.java @@ -24,11 +24,13 @@ public class DeviceTest extends DataTest { protected Device getRandomInstance(long seed, StringGenerator g) { random.setSeed(seed); String family = g.getString(256); - return new Device(family); + String brand = g.getString(256); + String model = g.getString(256); + return new Device(family, brand, model); } @Override protected Device getBlankInstance() { - return new Device(null); + return new Device(null, null, null); } } \ No newline at end of file diff --git a/src/test/java/ua_parser/ParserTest.java b/src/test/java/ua_parser/ParserTest.java index 525a092..82e5266 100644 --- a/src/test/java/ua_parser/ParserTest.java +++ b/src/test/java/ua_parser/ParserTest.java @@ -81,10 +81,10 @@ public void testParseAll() { Client expected1 = new Client(new UserAgent("Firefox", "3", "5", "5"), new OS("Mac OS X", "10", "4", null, null), - new Device("Other")); + new Device("Other", null, null)); Client expected2 = new Client(new UserAgent("Mobile Safari", "5", "1", null), new OS("iOS", "5", "1", "1", null), - new Device("iPhone")); + new Device("iPhone", "Apple", "iPhone")); assertThat(parser.parse(agentString1), is(expected1)); assertThat(parser.parse(agentString2), is(expected2));