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

Optimization to avoid multiple compilation of regex and few bug fixes. #2

Open
wants to merge 2 commits 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
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<groupId>ua_parser</groupId>
<artifactId>ua-parser</artifactId>
<packaging>jar</packaging>
<version>1.3.1-SNAPSHOT</version>
<version>1.3.1.sociablelabs-SNAPSHOT</version>
<name>ua-parser</name>
<url>https://github.com/sociable/uap-java</url>
<properties>
Expand Down
21 changes: 10 additions & 11 deletions src/main/java/ua_parser/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,22 @@ public Client(UserAgent userAgent, OS os, Device device, Platform platform, Manu
* @return A string with format X.Y.Z
*/
public String calculateBrowserVersion() {
final String browserVersion;

// Build the browser version from all it's parts
if (this.userAgent.major != null) {
browserVersion = this.userAgent.major;
final StringBuilder builder = new StringBuilder(this.userAgent.major);

if (this.userAgent.minor != null) {
browserVersion.concat("."+this.userAgent.minor);
builder.append('.').append(this.userAgent.minor);

if (this.userAgent.patch != null) {
browserVersion.concat("."+this.userAgent.patch);
builder.append('.').append(this.userAgent.patch);
}
}
return builder.toString();
} else {
browserVersion = Constants.UNDEFINED;
return Constants.UNDEFINED;
}
return browserVersion;
}

/**
Expand All @@ -68,17 +67,17 @@ public String calculateBrowserVersion() {
* @return iOS 8, iOS 7, Android 2.0
*/
public String calculateOSName() {
final String osName = this.os.family;
final StringBuilder osName = new StringBuilder(this.os.family);

if(this.os.major != null) {
osName.concat(" " + this.os.major);
osName.append(' ').append(this.os.major);

if (this.os.minor != null) {
osName.concat("." + this.os.minor);
osName.append('.').append(this.os.minor);
}
}

return osName;
return osName.toString();
}

@Override
Expand Down Expand Up @@ -106,4 +105,4 @@ public String toString() {
userAgent, os, device);
}

}
}
4 changes: 2 additions & 2 deletions src/main/java/ua_parser/DeviceParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public static DeviceParser fromList(List<Map<String,String>> configList) {
return new DeviceParser(configPatterns);
}

protected static DevicePattern patternFromMap(Map<String, String> configMap) {
private static DevicePattern patternFromMap(Map<String, String> configMap) {
String regex = configMap.get("regex");
if (regex == null) {
throw new IllegalArgumentException("Device is missing regex");
Expand Down Expand Up @@ -115,4 +115,4 @@ private List<String> getSubstitutions(String deviceReplacement) {

}

}
}
2 changes: 1 addition & 1 deletion src/main/java/ua_parser/Manufacture.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public boolean equals(Object other) {
if (!(other instanceof Manufacture)) return false;

final Manufacture o = (Manufacture) other;
return ((this.name != null) && this.name.equals(o.name)) || this.name == o.name;
return this.name == null ? o.name == null : this.name.equals(o.name);
}

@Override
Expand Down
51 changes: 24 additions & 27 deletions src/main/java/ua_parser/ManufactureParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
package ua_parser;

import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;

import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Expand All @@ -19,7 +21,18 @@
public class ManufactureParser {
private final Logger LOGGER = Logger.getLogger(PlatformParser.class.getName());

public ManufactureParser() { }
public ManufactureParser() {
}

private static final Multimap<String, Pattern> MANUFACTURER_OS_PATTERN_MAP =
ImmutableMultimap.<String, Pattern>builder()
.put(Constants.APPLE, Pattern.compile("iOS"))
.put(Constants.APPLE, Pattern.compile("OS X"))
.put(Constants.APPLE, Pattern.compile("Macintosh"))
.put(Constants.GOOGLE, Pattern.compile("Android"))
.put(Constants.MICROSOFT, Pattern.compile("Windows"))
.put(Constants.LINUX, Pattern.compile("Linux"))
.build();

/**
* Calculate the manufacture of the hosting OS from the User Agent
Expand All @@ -28,37 +41,21 @@ public ManufactureParser() { }
* @return The manufacture of the host OS
*/
public Manufacture parse(String uaString) {
for (Map.Entry<String, String> entry : getManufactureOsMap().entries()) {

// Itterate over all expressions assigned to a key
for (String regex : getManufactureOsMap().get(entry.getKey())) {
final Pattern pattern = Pattern.compile(regex);
final Matcher matcher = pattern.matcher(uaString);

if (matcher.find()) {
LOGGER.info("Found match in manufacture with key: " + entry.getKey());
return new Manufacture(entry.getKey());
for (Map.Entry<String, Pattern> entry : MANUFACTURER_OS_PATTERN_MAP.entries()) {
final String key = entry.getKey();
final Pattern pattern = entry.getValue();
final Matcher matcher = pattern.matcher(uaString);

if (matcher.find()) {
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.finest("Found match in manufacture with key: " + key);
}
return new Manufacture(key);
}
}

LOGGER.info("Could not find a manufacturer, using default manufaacture value");
LOGGER.finest("Could not find a manufacturer, using default manufacture value");
return new Manufacture(Constants.OTHER);
}

/**
* A simple map with manufactures along with a regex for it's representation
*
* @return a immutable map with manufacture => regex
*/
private static ImmutableMultimap<String, String> getManufactureOsMap() {
return ImmutableMultimap.<String, String>builder().
put(Constants.APPLE, "iOS").
put(Constants.APPLE, "OS X").
put(Constants.APPLE, "Macintosh").
put(Constants.GOOGLE, "Android").
put(Constants.MICROSOFT, "Windows").
put(Constants.LINUX, "Linux").
build();
}
}
5 changes: 4 additions & 1 deletion src/main/java/ua_parser/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.yaml.snakeyaml.Yaml;
Expand Down Expand Up @@ -51,7 +52,9 @@ public Parser(InputStream regexYaml) {
}

public Client parse(String agentString) {
LOGGER.info("Parsing UA: " + agentString);
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.finest("Parsing UA: " + agentString);
}
UserAgent ua = parseUserAgent(agentString);
OS os = parseOS(agentString);
Device device = deviceParser.parse(agentString);
Expand Down
33 changes: 22 additions & 11 deletions src/main/java/ua_parser/PlatformParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,30 @@
*/
package ua_parser;

import com.google.common.collect.ImmutableMap;

import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PlatformParser {
private final Map<String, String> mobileDevicePatters;
private final Map<String, String> tabletDevicePatters;
private final Map<String, Pattern> mobileDevicePatters;
private final Map<String, Pattern> tabletDevicePatters;
private final Logger LOGGER = Logger.getLogger(PlatformParser.class.getName());

public PlatformParser(Map<String, String> mobileDevicePatters, Map<String, String> tabletDevicePatters) {
this.mobileDevicePatters = mobileDevicePatters;
this.tabletDevicePatters = tabletDevicePatters;
this.mobileDevicePatters = toPatternMap(mobileDevicePatters);
this.tabletDevicePatters = toPatternMap(tabletDevicePatters);
}

private static Map<String, Pattern> toPatternMap(Map<String, String> stringPatternMap) {
final ImmutableMap.Builder<String, Pattern> builder = ImmutableMap.<String, Pattern>builder();
for (Map.Entry<String,String> entry : stringPatternMap.entrySet()) {
builder.put(entry.getKey(), Pattern.compile(entry.getValue()));
}
return builder.build();
}

public Platform parse(String uaString) {
Expand All @@ -35,27 +46,27 @@ public Platform parse(String uaString) {
}

private boolean isMobile(String ua) {
LOGGER.info("Checking For Mobile Device");
return runPatternsOnString(mobileDevicePatters, ua);
}

private boolean isTablet(String ua) {
LOGGER.info("Checking For Tablet Device");
return runPatternsOnString(tabletDevicePatters, ua);
}

private boolean runPatternsOnString(Map<String, String> patterns, String input) {
for (Map.Entry<String, String> entry : patterns.entrySet()) {
final Pattern pattern = Pattern.compile(entry.getValue());
private boolean runPatternsOnString(Map<String, Pattern> patterns, String input) {
for (Map.Entry<String, Pattern> entry : patterns.entrySet()) {
final Pattern pattern = entry.getValue();
final Matcher matcher = pattern.matcher(input);

if (matcher.find()) {
// Found a match
LOGGER.info("Found match in device with key: " + entry.getKey());
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.finest("Found match in device with key: " + entry.getKey());
}
return true;
}
}
LOGGER.info("No match found, using default platform value");
LOGGER.finest("No match found, using default platform value");
return false;
}
}