Skip to content

Commit

Permalink
adding Brand and Model support
Browse files Browse the repository at this point in the history
  • Loading branch information
nsonntag committed Mar 19, 2016
1 parent 5193d40 commit bdef99c
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 35 deletions.
23 changes: 17 additions & 6 deletions src/main/java/ua_parser/Device.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, String> m) {
return new Device((String) m.get("family"));
return new Device(m.get("family"), m.get("brand"), m.get("model"));
}

@Override
Expand All @@ -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 + '"');
}
}
72 changes: 47 additions & 25 deletions src/main/java/ua_parser/DeviceParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -39,15 +40,19 @@ public Device parse(String agentString) {
return null;
}

String device = null;
Map<String, String> 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<Map<String,String>> configList) {
Expand All @@ -65,47 +70,64 @@ protected static DevicePattern patternFromMap(Map<String, String> 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<String, String> 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<String, String> replacements = new HashMap<String, String>();
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<String> getSubstitutions(String deviceReplacement) {
Matcher matcher = SUBSTITUTIONS_PATTERN.matcher(deviceReplacement);
private List<String> getSubstitutions(String replacement) {
Matcher matcher = SUBSTITUTIONS_PATTERN.matcher(replacement);
List<String> substitutions = new ArrayList<String>();
while (matcher.find()) {
substitutions.add(matcher.group());
Expand Down
6 changes: 4 additions & 2 deletions src/test/java/ua_parser/DeviceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ public class DeviceTest extends DataTest<Device> {
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);
}
}
4 changes: 2 additions & 2 deletions src/test/java/ua_parser/ParserTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down

0 comments on commit bdef99c

Please sign in to comment.