Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Device's for brand and support #91

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 18 additions & 7 deletions src/main/java/ua_parser/Device.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,20 @@
*/
public class Device {

public static final Device OTHER = new Device("Other");
public static final Device OTHER = new Device("Other", null, null);

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 @@ -43,17 +47,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 + '"');
}
}
69 changes: 44 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.concurrent.CopyOnWriteArrayList;
Expand All @@ -41,10 +42,11 @@ public Device parse(String agentString) {
return null;
}

String device;
Map<String, String> replacements = null;
for (DevicePattern p : patterns) {
if ((device = p.match(agentString)) != null) {
return new Device(device);
if ((replacements = p.match(agentString)) != null) {
return new Device(replacements.get("device_replacement"), replacements.get("brand_replacement"),
replacements.get("model_replacement"));
}
}
return Device.OTHER;
Expand All @@ -70,47 +72,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<>();
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("Mac"));
new Device("Mac", "Apple", "Mac"));
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"));

MatcherAssert.assertThat(parser.parse(agentString1), is(expected1));
MatcherAssert.assertThat(parser.parse(agentString2), is(expected2));
Expand Down