Author: wkeil Date: Sun Nov 29 23:36:18 2015 New Revision: 1717136 URL: http://svn.apache.org/viewvc?rev=1717136&view=rev Log: DMAP-54: Improve Console example
Task-Url: https://issues.apache.org/jira/browse/DMAP-54 DMAP-155: UA changes with Windows 10 update Task-Url: https://issues.apache.org/jira/browse/DMAP-155 Added: devicemap/trunk/clients/1.0/java/client/ (with props) devicemap/trunk/clients/1.0/java/client/pom.xml devicemap/trunk/clients/1.0/java/client/src/ devicemap/trunk/clients/1.0/java/client/src/main/ devicemap/trunk/clients/1.0/java/client/src/main/java/ devicemap/trunk/clients/1.0/java/client/src/main/java/org/ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/DeviceMapClient.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/DeviceMapFactory.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/cmd/ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/cmd/Main.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/Device.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/DeviceType.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/Pattern.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/PatternSet.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/Loader.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/LoaderFactory.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/LoaderOption.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/Resource.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/impl/ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/impl/DDRLoader.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/impl/NoopLoader.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/impl/UninitializedLoader.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/parser/ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/parser/JsonParser.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/parser/XMLParser.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/resource/ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/resource/FileResource.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/resource/JarResource.java devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/resource/URLResource.java devicemap/trunk/clients/1.0/java/client/src/test/ devicemap/trunk/clients/1.0/java/client/src/test/java/ devicemap/trunk/clients/1.0/java/client/src/test/java/org/ devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/ devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/ devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientFileTestOptional.java devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientJarTest.java devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientTest.java devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientUnitTest.java devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientUrlTestOptional.java devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/loader/ devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/loader/parser/ devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/loader/parser/XMLParserTest.java devicemap/trunk/clients/1.0/java/client/src/test/resources/ devicemap/trunk/clients/1.0/java/client/src/test/resources/uas.data devicemap/trunk/clients/1.0/java/console/ (with props) devicemap/trunk/clients/1.0/java/console/pom.xml devicemap/trunk/clients/1.0/java/console/src/ devicemap/trunk/clients/1.0/java/console/src/main/ devicemap/trunk/clients/1.0/java/console/src/main/java/ devicemap/trunk/clients/1.0/java/console/src/main/java/org/ devicemap/trunk/clients/1.0/java/console/src/main/java/org/apache/ devicemap/trunk/clients/1.0/java/console/src/main/java/org/apache/devicemap/ devicemap/trunk/clients/1.0/java/console/src/main/java/org/apache/devicemap/console/ devicemap/trunk/clients/1.0/java/console/src/main/java/org/apache/devicemap/console/Main.java Removed: devicemap/trunk/clients/1.0/java/src/ Modified: devicemap/trunk/clients/1.0/java/pom.xml Propchange: devicemap/trunk/clients/1.0/java/client/ ------------------------------------------------------------------------------ --- svn:ignore (added) +++ svn:ignore Sun Nov 29 23:36:18 2015 @@ -0,0 +1,4 @@ +target +.settings +.classpath +.project Added: devicemap/trunk/clients/1.0/java/client/pom.xml URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/pom.xml?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/pom.xml (added) +++ devicemap/trunk/clients/1.0/java/client/pom.xml Sun Nov 29 23:36:18 2015 @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.devicemap</groupId> + <artifactId>devicemap-java</artifactId> + <version>1.1.1-SNAPSHOT</version> + </parent> + + <groupId>org.apache.devicemap</groupId> + <artifactId>devicemap-client</artifactId> + <packaging>jar</packaging> + <name>Apache DeviceMap Java Client</name> + <description>Apache DeviceMap Java API</description> + <url>http://devicemap.apache.org/</url> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <scm> + <connection>scm:svn:http://svn.apache.org/repos/asf/devicemap/trunk/devicemap/java/classifier</connection> + <developerConnection>scm:svn:https://svn.apache.org/repos/asf/devicemap/trunk/devicemap/java/classifier</developerConnection> + <url>http://svn.apache.org/viewvc/devicemap/trunk/devicemap/java/classifier</url> + </scm> + + <dependencies> + <dependency> + <groupId>org.apache.devicemap</groupId> + <artifactId>devicemap-data</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>1.6</source> + <target>1.6</target> + <debug>true</debug> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + </plugin> + </plugins> + </build> + +</project> Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/DeviceMapClient.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/DeviceMapClient.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/DeviceMapClient.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/DeviceMapClient.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,198 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap; + +import java.io.IOException; +import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.devicemap.data.Device; +import org.apache.devicemap.loader.LoaderOption; +import org.apache.devicemap.data.DeviceType; +import org.apache.devicemap.data.Pattern; +import org.apache.devicemap.loader.LoaderFactory; + +public class DeviceMapClient { + + private final static Logger LOG = Logger.getLogger(DeviceMapClient.class.getName()); + private final static java.util.regex.Pattern TEXT_SPLIT_PATTERN = java.util.regex.Pattern.compile(" |-|_|/|\\\\|\\[|\\]|\\(|\\)|;"); + + private static long initCount = 0; + + //indexes + private Map<String, DeviceType> devices; + private Map<String, List<DeviceType>> patterns; + + private final Device unknown; + + public DeviceMapClient() { + devices = null; + patterns = null; + Map<String, String> uAttributes = new HashMap<String, String>(); + uAttributes.put("id", Device.UNKNOWN_ID); + uAttributes = Collections.unmodifiableMap(uAttributes); + unknown = new Device(Device.UNKNOWN_ID, uAttributes); + } + + public void initDeviceData(LoaderOption option) throws IOException { + initDeviceData(option, null); + } + + public synchronized void initDeviceData(LoaderOption option, String path) throws IOException { + devices = LoaderFactory.getLoader(option, path).getData(); + + initCount++; + + if (initCount % 1000 == 0) { + LOG.log(Level.WARNING, "Possible device data over-initialization detected"); + } + + if (devices == null) { + patterns = null; + return; + } + + createIndex(); + } + + private void createIndex() { + patterns = new HashMap<String, List<DeviceType>>(8000); + + for (DeviceType device : devices.values()) { + for (Pattern pattern : device.getPatternSet().getPatterns()) { + for (int i = 0; i < pattern.getPatternParts().size(); i++) { + String part = pattern.getPatternParts().get(i); + + //duplicate + if (patterns.get(part) != null) { + if (i == (pattern.getPatternParts().size() - 1) && !patterns.get(part).contains(device)) { + patterns.get(part).add(device); + } + } else { + List<DeviceType> single = new ArrayList<DeviceType>(); + single.add(device); + patterns.put(part, single); + } + } + } + } + } + + public Map<String, String> classify(String text) { + if (devices == null) { + throw new RuntimeException("Uninitialized device index"); + } + + if (text == null) { + return null; + } + + Set<String> hitPatterns = new HashSet<String>(); + Set<DeviceType> hitDevices = new HashSet<DeviceType>(); + DeviceType winner = null; + Pattern winnerPattern = null; + + LOG.log(Level.FINE, "classify: ''{0}''", text); + + List<String> parts = split(text); + + //generate ngrams upto size 4 + for (int i = 0; i < parts.size(); i++) { + String pattern = ""; + for (int j = 0; j < 4 && (j + i) < parts.size(); j++) { + pattern += parts.get(i + j); + List<DeviceType> dlist = patterns.get(pattern); + if (dlist != null) { + hitPatterns.add(pattern); + hitDevices.addAll(dlist); + for (DeviceType device : dlist) { + LOG.log(Level.FINER, "Hit found: ''{0}'' => id: ''{1}'' {2}", new Object[]{pattern, device.getId(), device.getPatternSet()}); + } + } + } + } + + //look for the strongest hit + for (DeviceType device : hitDevices) { + Pattern pattern = device.getPatternSet().isValid(hitPatterns); + if (pattern == null) { + continue; + } + + LOG.log(Level.FINER, "Hit candidate: ''{0}'' => ({1},{2})", new Object[]{device.getId(), pattern.getType(), pattern.getRank()}); + + if (winnerPattern == null || pattern.getRank() > winnerPattern.getRank()) { + winner = device; + winnerPattern = pattern; + } + } + + if (winner != null) { + LOG.log(Level.FINE, "Result: {0}", winner); + return winner.getAttributes(); + } else { + return null; + } + } + + private static List<String> split(String text) { + String[] parts = TEXT_SPLIT_PATTERN.split(text); + List<String> nonemptyParts = new ArrayList<String>(); + for (String part : parts) { + String normalizedPart = Pattern.normalize(part); + if (normalizedPart != null && !normalizedPart.isEmpty()) + nonemptyParts.add(normalizedPart); + } + return nonemptyParts; + } + + public Device classifyDevice(String text) { + Map<String, String> m = classify(text); + if (m == null) { + return unknown; + } + return new Device(m.get("id"), m); + } + + public int getDeviceCount() { + if (devices == null) { + return -1; + } + return devices.size(); + } + + public int getPatternCount() { + if (patterns == null) { + return -1; + } + return patterns.size(); + } + + public long getNodeCount() { + if (patterns == null) { + return -1; + } + long count = 0; + for (List<DeviceType> pDevices : patterns.values()) { + count += pDevices.size(); + } + return count; + } +} Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/DeviceMapFactory.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/DeviceMapFactory.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/DeviceMapFactory.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/DeviceMapFactory.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,62 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap; + +import java.io.IOException; +import org.apache.devicemap.loader.LoaderOption; + +public class DeviceMapFactory { + + private static DeviceMapClient client = null; + private static volatile boolean initialized = false; + + private static final LoaderOption DEFAULT = LoaderOption.JAR; + + private DeviceMapFactory() { + } + + public static DeviceMapClient getClient() { + return getClient(DEFAULT, null); + } + + public static DeviceMapClient getClient(LoaderOption option) { + return getClient(option, null); + } + + public static DeviceMapClient getClient(LoaderOption option, String path) { + if (!initialized) { + synchronized (DeviceMapFactory.class) { + if (!initialized) { + client = new DeviceMapClient(); + try { + client.initDeviceData(option, path); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + initialized = true; + } + } + } + return client; + } + + public static void resetClient() { + initialized = false; + } +} Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/cmd/Main.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/cmd/Main.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/cmd/Main.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/cmd/Main.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,153 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap.cmd; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.util.logging.ConsoleHandler; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.devicemap.DeviceMapClient; +import org.apache.devicemap.data.Device; +import org.apache.devicemap.loader.LoaderOption; +import org.apache.devicemap.loader.impl.DDRLoader; + +/** + * @author Reza Naghibi + * @author Werner Keil + */ +public class Main { + + public static void main(String[] args) throws Exception { + + System.out.println("DeviceMap Java Console " + DeviceMapClient.class.getPackage().getImplementationVersion()); + + if(args.length == 0) { + System.out.println("Usage: -h for help"); + } + + String loaderPath = null; + LoaderOption option = LoaderOption.UNINITIALIZED; + String parameter = null; + boolean debug = true; + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("-f")) { + option = LoaderOption.FOLDER; + if (args.length > (++i)) { + loaderPath = args[i]; + } + } else if (args[i].equals("-u")) { + option = LoaderOption.URL; + if (args.length > (++i)) { + loaderPath = args[i]; + } + } else if (args[i].equals("-j")) { + option = LoaderOption.JAR; + } else if (args[i].equals("-d")) { + debug = false; + } else if (args[i].startsWith("-h") || args[i].startsWith("--h")) { + System.out.println("Usage: " + Main.class.getName() + " [OPTIONS] [FILE|STRING]\n"); + System.out.println(" -f <path> load DeviceMap resouces from folder or \"default\""); + System.out.println(" -j load DeviceMap resouces from jar file in classpath"); + System.out.println(" -u <url> load DeviceMap resouces from URL or \"default\""); + System.out.println(" -d no debug logging"); + System.out.println(" FILE text file of strings"); + System.out.println(" STRING test string"); + + return; + } //[test string] | [test file] + else if(!args[i].isEmpty()) { + parameter = args[i]; + } + } + + if(debug) { + Logger.getLogger(DeviceMapClient.class.getName()).setLevel(Level.ALL); + Logger.getLogger(DDRLoader.class.getName()).setLevel(Level.ALL); + for (Handler h : Logger.getLogger(DeviceMapClient.class.getName()).getParent().getHandlers()) { + if (h instanceof ConsoleHandler) { + h.setLevel(Level.ALL); + } + } + } + + if ("default".equals(loaderPath)) { + loaderPath = null; + } + + DeviceMapClient client = new DeviceMapClient(); + final long start = System.currentTimeMillis(); + client.initDeviceData(option, loaderPath); + long diff = System.currentTimeMillis() - start; + + System.out.println("Loaded " + client.getDeviceCount() + " devices with " + client.getPatternCount() + + " patterns and " + client.getNodeCount() + " nodes in " + diff + "ms"); + + final String test = "Mozilla/5.0 (Linux; U; Android 2.2; en; HTC Aria A6380 Build/ERE27) AppleWebKit/540.13+ (KHTML, like Gecko) Version/3.1 Mobile Safari/524.15.0"; + long startn = System.nanoTime(); + Device device = client.classifyDevice(test); + long diffn = (System.nanoTime() - startn) / 1000; + + System.out.println("Test lookup: '" + device.getId() + "' time: " + diffn + "usec"); + + if (parameter == null) { + } else if ((new File(parameter)).exists()) { + System.out.println("Text file: " + parameter); + + int count = 0; + int total = 0; + + BufferedReader in = new BufferedReader(new FileReader(parameter)); + String line; + + while ((line = in.readLine()) != null) { + System.out.println("Text: '" + line + "'"); + startn = System.nanoTime(); + device = client.classifyDevice(line); + diffn = System.nanoTime() - startn; + total += diffn; + count++; + + System.out.println("Text lookup " + count + ": '" + device.getId() + "' time: " + (diffn / 1000) + "usec"); + } + + in.close(); + + if (count == 0) { + count = 1; + } + + total /= count; + + System.out.println("TOTAL lookups: " + count + ", average time: " + (total / 1000) + "usec"); + } else { + System.out.println("Text: '" + parameter + "'"); + + startn = System.nanoTime(); + device = client.classifyDevice(parameter); + diffn = System.nanoTime() - startn; + System.out.println("Text lookup: '" + device.getId() + "' time: " + (diffn / 1000) + "usec"); + System.out.println("DeviceMap JSON => " + device.toString()); + } + } +} Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/Device.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/Device.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/Device.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/Device.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,60 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap.data; + +import java.util.Map; +import org.apache.devicemap.loader.parser.JsonParser; + +public class Device { + + public static final String UNKNOWN_ID = "unknown"; + + private final String id; + + private final Map<String, String> attributes; + + public Device(String id, Map<String, String> attributes) { + this.id = id; + this.attributes = attributes; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append('{'); + sb.append(JsonParser.outputKeyValue("id",id)).append(','); + sb.append(JsonParser.outputString("attributes")).append(':').append(JsonParser.outputMap(attributes)); + sb.append('}'); + + return sb.toString(); + } + + public String getId() { + return id; + } + + public String getAttribute(String key) { + return attributes.get(key); + } + + public Map<String, String> getAttributes() { + return attributes; + } +} Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/DeviceType.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/DeviceType.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/DeviceType.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/DeviceType.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,84 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap.data; + +import java.util.Collections; +import java.util.Map; +import org.apache.devicemap.loader.parser.JsonParser; + +public class DeviceType { + + private String id; + + private String parentId; + + private final PatternSet pattern; + + private Map<String, String> attributes; + + public DeviceType() { + pattern = new PatternSet(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append('{'); + sb.append(JsonParser.outputKeyValue("id", id)).append(','); + sb.append(JsonParser.outputKeyValue("parentId", parentId)).append(','); + sb.append(JsonParser.outputString("pattern")).append(':').append(pattern.toString()).append(','); + sb.append(JsonParser.outputString("attributes")).append(':').append(JsonParser.outputMap(attributes)); + sb.append('}'); + + return sb.toString(); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getParentId() { + return parentId; + } + + public void setParentId(String parentId) { + this.parentId = parentId; + } + + public PatternSet getPatternSet() { + return pattern; + } + + public Map<String, String> getAttributes() { + return attributes; + } + + public void setAttributes(Map<String, String> attributes) { + this.attributes = attributes; + } + + public void lockAttributes() { + attributes = Collections.unmodifiableMap(attributes); + } +} Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/Pattern.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/Pattern.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/Pattern.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/Pattern.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,121 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap.data; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import org.apache.devicemap.loader.parser.JsonParser; + +public class Pattern { + + private final List<String> pattern; + + private final String type; + + private final int rank; + + private final int boost; + + public Pattern(String pattern, String type, int boost) { + this(Arrays.asList(pattern), type, boost); + } + + public Pattern(List<String> pattern, String type, int boost) { + this.pattern = pattern; + this.type = type; + this.boost = boost; + rank = genRank(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append('{'); + sb.append(JsonParser.outputKeyValue("type", type)).append(','); + sb.append(JsonParser.outputKeyRValue("rank", rank)).append(','); + sb.append(JsonParser.outputKeyRValue("boost", boost)).append(','); + sb.append(JsonParser.outputString("pattern")).append(':').append(JsonParser.outputList(pattern, true)); + sb.append('}'); + + return sb.toString(); + } + + private int genRank() { + int r = 0; + + if ("weak".equals(type)) { + r += 1000; + } + + r += pattern.size() * 100; + + for (String part : pattern) { + r += part.length(); + } + + return r; + } + + public int getRank() { + return rank + boost; + } + + public String getType() { + return type; + } + + public List<String> getPatternParts() { + return pattern; + } + + public boolean isValid(Set<String> patternsToMatch) { + for (String part : pattern) { + if (!patternsToMatch.contains(part)) { + return false; + } + } + return true; + } + + /* + * normalizes a pattern + */ + public static String normalize(String p) { + if (p == null) { + return p; + } + + p = p.toLowerCase().trim(); + + p = p.replaceAll("\\[bb\\]", "b"); + + StringBuilder ret = new StringBuilder(); + + for (int i = 0; i < p.length(); i++) { + Character c = p.charAt(i); + if (Character.isLetter(c) || Character.isDigit(c)) { + ret.append(c); + } + } + + return ret.toString(); + } +} Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/PatternSet.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/PatternSet.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/PatternSet.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/data/PatternSet.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,87 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap.data; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import org.apache.devicemap.loader.parser.JsonParser; + +public class PatternSet { + + private final List<Pattern> patterns; + + public PatternSet() { + patterns = new ArrayList<Pattern>(); + } + + @Override + public String toString() { + List<String> orPatterns = new ArrayList<String>(); + for (Pattern pattern : patterns) { + orPatterns.add(pattern.toString()); + } + return JsonParser.outputList(orPatterns, false); + } + + /* + * add the patterns together as an inner list (AND) + */ + public void setAndPattern(List<String> patterns, String type) { + this.patterns.add(new Pattern(patterns, type, 0)); + } + + /* + * add each pattern on its own list (OR) + */ + public void setOrPattern(List<String> patterns, String type) { + for (String pattern : patterns) { + setPattern(pattern, type); + } + } + + /* + * add a single pattern (OR) + */ + public void setPattern(String pattern, String type) { + patterns.add(new Pattern(pattern, type, 0)); + } + + public List<Pattern> getPatterns() { + return patterns; + } + + /* + * does a pattern match + */ + public Pattern isValid(Set<String> patternsToMatch) { + Pattern winner = null; + + for (Pattern pattern : this.patterns) { + if (!pattern.isValid(patternsToMatch)) { + continue; + } + if (winner == null || pattern.getRank() > winner.getRank()) { + winner = pattern; + } + } + + return winner; + } +} Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/Loader.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/Loader.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/Loader.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/Loader.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,29 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap.loader; + +import java.io.IOException; +import java.util.Map; + +import org.apache.devicemap.data.DeviceType; + +public interface Loader { + + public Map<String, DeviceType> getData() throws IOException; +} Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/LoaderFactory.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/LoaderFactory.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/LoaderFactory.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/LoaderFactory.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,48 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ + +package org.apache.devicemap.loader; + +import org.apache.devicemap.loader.impl.DDRLoader; +import org.apache.devicemap.loader.resource.JarResource; +import org.apache.devicemap.loader.resource.FileResource; +import org.apache.devicemap.loader.impl.NoopLoader; +import org.apache.devicemap.loader.resource.URLResource; +import org.apache.devicemap.loader.impl.UninitializedLoader; + +public class LoaderFactory { + + public static Loader getLoader(LoaderOption option, String path) { + switch (option) { + case JAR: { + return new DDRLoader(new JarResource(path)); + } + case FOLDER: { + return new DDRLoader(new FileResource(path)); + } + case URL: { + return new DDRLoader(new URLResource(path)); + } + case NOOP: { + return new NoopLoader(); + } + } + return new UninitializedLoader(); + } +} Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/LoaderOption.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/LoaderOption.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/LoaderOption.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/LoaderOption.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,23 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap.loader; + +public enum LoaderOption { + JAR, FOLDER, URL, NOOP, UNINITIALIZED; +}; Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/Resource.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/Resource.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/Resource.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/Resource.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,27 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap.loader; + +import java.io.IOException; +import java.io.InputStream; + +public interface Resource { + + public InputStream getResource(String file) throws IOException; +} Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/impl/DDRLoader.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/impl/DDRLoader.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/impl/DDRLoader.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/impl/DDRLoader.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,255 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap.loader.impl; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.apache.devicemap.data.DeviceType; +import org.apache.devicemap.data.Pattern; +import org.apache.devicemap.loader.Loader; +import org.apache.devicemap.loader.Resource; +import org.apache.devicemap.loader.parser.XMLParser; + +public class DDRLoader implements Loader { + + private final static Logger LOG = Logger.getLogger(DDRLoader.class.getName()); + + private static final String DEVICE_DATA = "DeviceDataSource.xml"; + private static final String DEVICE_DATA_PATCH = "DeviceDataSourcePatch.xml"; + private static final String BUILDER_DATA = "BuilderDataSource.xml"; + private static final String BUILDER_DATA_PATCH = "BuilderDataSourcePatch.xml"; + + private final Map<String, DeviceType> devices; + + private final Resource resourceLoader; + + public DDRLoader(Resource resourceLoader) { + devices = new HashMap<String, DeviceType>(5000); + this.resourceLoader = resourceLoader; + } + + @Override + public Map<String, DeviceType> getData() throws IOException { + long start = System.currentTimeMillis(); + + BufferedReader ddin = new BufferedReader(new InputStreamReader(resourceLoader.getResource(DEVICE_DATA), "UTF-8")); + loadDeviceData(ddin); + ddin.close(); + + long diff = System.currentTimeMillis() - start; + LOG.log(Level.FINE, "Loaded " + DEVICE_DATA + " in {0}ms", diff); + + try { + start = System.currentTimeMillis(); + + BufferedReader ddpin = new BufferedReader(new InputStreamReader(resourceLoader.getResource(DEVICE_DATA_PATCH), "UTF-8")); + loadDeviceData(ddpin); + ddpin.close(); + + diff = System.currentTimeMillis() - start; + LOG.log(Level.FINE, "Loaded " + DEVICE_DATA_PATCH + " in {0}ms", diff); + } catch (FileNotFoundException ex) { + LOG.log(Level.WARNING, "File not found " + DEVICE_DATA_PATCH + ": {0}", ex.toString()); + } + + setParentAttributes(); + + start = System.currentTimeMillis(); + + BufferedReader bin = new BufferedReader(new InputStreamReader(resourceLoader.getResource(BUILDER_DATA), "UTF-8")); + loadDevicePatterns(bin); + bin.close(); + + diff = System.currentTimeMillis() - start; + LOG.log(Level.FINE, "Loaded " + BUILDER_DATA + " in {0}ms", diff); + + try { + start = System.currentTimeMillis(); + + BufferedReader bpin = new BufferedReader(new InputStreamReader(resourceLoader.getResource(BUILDER_DATA_PATCH), "UTF-8")); + loadDevicePatterns(bpin); + bpin.close(); + + diff = System.currentTimeMillis() - start; + LOG.log(Level.FINE, "Loaded " + BUILDER_DATA_PATCH + " in {0}ms", diff); + } catch (FileNotFoundException ex) { + LOG.log(Level.WARNING, "File not found " + BUILDER_DATA_PATCH + ": {0}", ex.toString()); + } + + return getDevices(); + } + + /* + * loads device data from an InputStreamReader + */ + private void loadDeviceData(Reader in) throws IOException { + XMLParser parser = new XMLParser(in); + String tag; + DeviceType device = new DeviceType(); + Map<String, String> attributes = new HashMap<String, String>(); + + while (!(tag = parser.getNextTag()).isEmpty()) { + //new device found + if (tag.startsWith("<device ")) { + device.setId(XMLParser.getAttribute(tag, "id")); + device.setParentId(XMLParser.getAttribute(tag, "parentId")); + } else if (tag.equals("</device>")) { + + //add the device + if (device.getId() != null && !device.getId().isEmpty()) { + attributes.put("id", device.getId()); + device.setAttributes(attributes); + devices.put(device.getId(), device); + } + + //reset the device + device = new DeviceType(); + attributes = new HashMap<String, String>(); + } else if (tag.startsWith("<property ")) { + //add the property to the device + String key = XMLParser.getAttribute(tag, "name"); + String value = XMLParser.getAttribute(tag, "value"); + + attributes.put(key, value); + } + } + } + + /* + * loads patterns from an InputStreamReader + */ + private void loadDevicePatterns(Reader in) throws IOException { + XMLParser parser = new XMLParser(in); + String tag; + String builder = ""; + String type = ""; + DeviceType device = null; + String id = ""; + List<String> patterns = new ArrayList<String>(); + + while (!(tag = parser.getNextTag()).isEmpty()) { + //new builder found + if (tag.startsWith("<builder ")) { + builder = XMLParser.getAttribute(tag, "class"); + + if (builder.lastIndexOf(".") >= 0) { + builder = builder.substring(builder.lastIndexOf(".") + 1); + } + + type = "weak"; + if (builder.equals("SimpleDeviceBuilder")) { + type = "simple"; + } + } else if (tag.startsWith("<device ")) { + //new device found + id = XMLParser.getAttribute(tag, "id"); + device = devices.get(id); + } else if (tag.equals("</device>")) { + //add the device + if (device != null) { + //TwoStep is an AND pattern, also index the unigram + if (builder.equals("TwoStepDeviceBuilder")) { + device.getPatternSet().setAndPattern(patterns, type); + + String unigram = ""; + + for (String pattern : patterns) { + if (pattern.contains(unigram)) { + unigram = pattern; + } else { + unigram += pattern; + } + } + + device.getPatternSet().setPattern(unigram, type); + } else { + device.getPatternSet().setOrPattern(patterns, type); + } + } else { + LOG.log(Level.FINE, "ERROR: device not found: ''{0}''", id); + } + + //reset the device + device = null; + id = ""; + patterns = new ArrayList<String>(); + } else if (tag.equals("<value>")) { + //add the pattern to the device + String pattern = Pattern.normalize(parser.getTagValue()); + + if (pattern.isEmpty()) { + continue; + } + + patterns.add(pattern); + } + } + } + + /** + * Sets attributes from parents + */ + private void setParentAttributes() { + for (DeviceType device : devices.values()) { + mergeParent(device); + device.lockAttributes(); + } + } + + private void mergeParent(DeviceType device) { + String parentId = device.getParentId(); + + if (parentId == null) { + return; + } + + DeviceType parent = devices.get(parentId); + + if (parent == null) { + return; + } + + mergeParent(parent); + + for (String key : parent.getAttributes().keySet()) { + String value = parent.getAttributes().get(key); + + if (!device.getAttributes().containsKey(key)) { + device.getAttributes().put(key, value); + } + } + } + + /** + * @return the devices + */ + private Map<String, DeviceType> getDevices() { + return devices; + } +} Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/impl/NoopLoader.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/impl/NoopLoader.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/impl/NoopLoader.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/impl/NoopLoader.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,34 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap.loader.impl; + +import java.io.IOException; +import java.util.Collections; +import java.util.Map; + +import org.apache.devicemap.data.DeviceType; +import org.apache.devicemap.loader.Loader; + +public class NoopLoader implements Loader { + + @Override + public Map<String, DeviceType> getData() throws IOException { + return Collections.emptyMap(); + } +} Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/impl/UninitializedLoader.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/impl/UninitializedLoader.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/impl/UninitializedLoader.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/impl/UninitializedLoader.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,33 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap.loader.impl; + +import java.io.IOException; +import java.util.Map; + +import org.apache.devicemap.data.DeviceType; +import org.apache.devicemap.loader.Loader; + +public class UninitializedLoader implements Loader { + + @Override + public Map<String, DeviceType> getData() throws IOException { + return null; + } +} Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/parser/JsonParser.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/parser/JsonParser.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/parser/JsonParser.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/parser/JsonParser.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,81 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap.loader.parser; + +import java.util.List; +import java.util.Map; + +public class JsonParser { + + public static String outputString(String s) { + if (s == null) { + return "null"; + } + return "\"" + s.replace("\"", "\\\"").replace("\n", " ") + "\""; + } + + public static String outputKeyValue(String key, String value) { + StringBuilder sb = new StringBuilder(); + sb.append(outputString(key)); + sb.append(':'); + sb.append(outputString(value)); + return sb.toString(); + } + + public static String outputKeyRValue(String key, Object value) { + StringBuilder sb = new StringBuilder(); + sb.append(outputString(key)); + sb.append(':'); + sb.append(value); + return sb.toString(); + } + + public static String outputMap(Map<String, String> map) { + StringBuilder sb = new StringBuilder(); + for (String key : map.keySet()) { + String value = map.get(key); + if (sb.length() == 0) { + sb.append('{'); + } else { + sb.append(','); + } + sb.append(outputKeyValue(key, value)); + } + sb.append('}'); + return sb.toString(); + } + + public static String outputList(List<String> list, boolean format) { + StringBuilder sb = new StringBuilder(); + for (String value : list) { + if (sb.length() == 0) { + sb.append('['); + } else { + sb.append(','); + } + if (format) { + sb.append(outputString(value)); + } else { + sb.append(value); + } + } + sb.append(']'); + return sb.toString(); + } +} Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/parser/XMLParser.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/parser/XMLParser.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/parser/XMLParser.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/parser/XMLParser.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,129 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap.loader.parser; + +import java.io.IOException; +import java.io.Reader; + +public class XMLParser { + + private final Reader in; + + private char pre; + + public XMLParser(Reader in) { + this.in = in; + pre = 0; + } + + public String getNextTag() throws IOException { + StringBuilder ret = new StringBuilder(); + + int i; + boolean start = false; + + if (pre == '<') { + ret.append(pre); + pre = 0; + start = true; + } + + while ((i = in.read()) != -1) { + char c = (char) i; + if (c == '<') { + start = true; + ret.append(c); + } else if (start) { + ret.append(c); + } + + if(c == '>') { + if(ret.lastIndexOf("<!--") == 0 && (ret.lastIndexOf("-->") + 3) != ret.length()) { + continue; + } + break; + } + } + + if(ret.lastIndexOf("<!--") == 0) { + if((ret.lastIndexOf("-->") + 3) == ret.length()) { + return getNextTag(); + } else { + return ""; + } + } + + return ret.toString(); + } + + public String getTagValue() throws IOException { + StringBuilder ret = new StringBuilder(); + + int i; + + while ((i = in.read()) != -1) { + char c = (char) i; + if (c == '<') { + pre = '<'; + break; + } else { + ret.append(c); + } + } + + return parseEntities(ret.toString().trim()); + } + + public static String getAttribute(String tag, String name) { + int retpos = tag.toLowerCase().indexOf(name.toLowerCase() + "="); + + if (retpos == -1) { + return ""; + } + + String ret = tag.substring(retpos + name.length() + 1); + + if (ret.startsWith("\"")) { + ret = ret.substring(1); + int endpos = ret.indexOf("\""); + + if (endpos == -1) { + return ""; + } + + ret = ret.substring(0, endpos); + } else { + int endpos = ret.indexOf(" "); + + if (endpos == -1) { + return ""; + } + + ret = ret.substring(0, endpos); + } + + return parseEntities(ret); + } + + private static String parseEntities(String s) { + return s.replace(""", "\"").replace("&", "&") + .replace("'", "'").replace("<", "<") + .replace(">", ">"); + } +} Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/resource/FileResource.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/resource/FileResource.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/resource/FileResource.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/resource/FileResource.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,50 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap.loader.resource; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.devicemap.loader.Resource; + +public class FileResource implements Resource { + + private static final String DEFAULT_PATH = ""; + + private final String path; + + public FileResource(String path) { + if (path == null) { + this.path = DEFAULT_PATH; + } else if (path.isEmpty()) { + this.path = ""; + } else { + this.path = path + File.separatorChar; + } + } + + @Override + public InputStream getResource(String file) throws IOException { + String rpath = path + file; + return new FileInputStream(rpath); + } + +} Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/resource/JarResource.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/resource/JarResource.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/resource/JarResource.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/resource/JarResource.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,53 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap.loader.resource; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.devicemap.loader.Resource; + +public class JarResource implements Resource { + + private static final String DEFAULT_PATH = "/devicedata/"; + + private final String path; + + public JarResource(String path) { + if (path == null) { + this.path = DEFAULT_PATH; + } else { + this.path = path; + } + } + + @Override + public InputStream getResource(String file) throws IOException { + String rpath = path + file; + + InputStream in = JarResource.class.getResourceAsStream(rpath); + + if (in == null) { + throw new FileNotFoundException("Jar resource not found: " + path); + } + + return in; + } +} Added: devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/resource/URLResource.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/resource/URLResource.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/resource/URLResource.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/main/java/org/apache/devicemap/loader/resource/URLResource.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,48 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap.loader.resource; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import org.apache.devicemap.loader.Resource; + +public class URLResource implements Resource { + + //TODO: put on CDN of some kind + private static final String DEFAULT_PATH = "http://devicemap-vm.apache.org/data/latest"; + + private final String path; + + public URLResource(String path) { + if (path == null) { + this.path = DEFAULT_PATH; + } else { + this.path = path; + } + } + + @Override + public InputStream getResource(String file) throws IOException { + String rpath = path + "/" + file; + return new URL(rpath).openStream(); + } + +} Added: devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientFileTestOptional.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientFileTestOptional.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientFileTestOptional.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientFileTestOptional.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,69 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap; + +import java.io.FileNotFoundException; +import org.apache.devicemap.data.Device; +import org.junit.Assert; +import org.junit.Test; + +import org.apache.devicemap.loader.LoaderOption; + +public class DeviceMapClientFileTestOptional { + + @Test + public void deviceMapClientFolderTest() throws Exception { + DeviceMapClient client = new DeviceMapClient(); + + client.initDeviceData(LoaderOption.FOLDER, "../../../data/device-data/src/main/resources/devicedata"); + + String test = "Mozilla/5.0 (Linux; U; Android 2.2; en; HTC Aria A6380 Build/ERE27) AppleWebKit/540.13+ (KHTML, like Gecko) Version/3.1 Mobile Safari/524.15.0"; + + Device device = client.classifyDevice(test); + + Assert.assertEquals("test ua not htc aria", "HTC Aria", device.getId()); + } + + @Test + public void deviceMapClientFolderFailureTest() throws Exception { + DeviceMapClient client = new DeviceMapClient(); + + try { + client.initDeviceData(LoaderOption.FOLDER,"fail"); + Assert.fail("FileNotFoundException expected with invalid folder path"); + } catch(FileNotFoundException fnf) { + //pass + } catch(Exception ex) { + Assert.fail("FileNotFoundException expected with invalid folder path, got: "+ex.toString()); + } + } + + @Test + public void deviceMapFactoryFileTest() throws Exception { + String test = "Mozilla/5.0 (Linux; U; Android 2.2; en; HTC Aria A6380 Build/ERE27) AppleWebKit/540.13+ (KHTML, like Gecko) Version/3.1 Mobile Safari/524.15.0"; + + Device device = DeviceMapFactory.getClient(LoaderOption.FOLDER, "../../../data/device-data/src/main/resources/devicedata").classifyDevice(test); + + Assert.assertEquals("test ua not htc aria", "HTC Aria", device.getId()); + + device = DeviceMapFactory.getClient(LoaderOption.FOLDER, "../../../data/device-data/src/main/resources/devicedata").classifyDevice(test); + + Assert.assertEquals("2nd test ua not htc aria", "HTC Aria", device.getId()); + } +} Added: devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientJarTest.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientJarTest.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientJarTest.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientJarTest.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,69 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap; + +import java.io.FileNotFoundException; +import org.apache.devicemap.data.Device; +import org.junit.Assert; +import org.junit.Test; + +import org.apache.devicemap.loader.LoaderOption; + +public class DeviceMapClientJarTest { + + @Test + public void deviceMapClientJarTest() throws Exception { + DeviceMapClient client = new DeviceMapClient(); + + client.initDeviceData(LoaderOption.JAR); + + String test = "Mozilla/5.0 (Linux; U; Android 2.2; en; HTC Aria A6380 Build/ERE27) AppleWebKit/540.13+ (KHTML, like Gecko) Version/3.1 Mobile Safari/524.15.0"; + + Device device = client.classifyDevice(test); + + Assert.assertEquals("test ua not htc aria", "HTC Aria", device.getId()); + } + + @Test + public void deviceMapClientJarFailureTest() throws Exception { + DeviceMapClient client = new DeviceMapClient(); + + try { + client.initDeviceData(LoaderOption.JAR,"fail"); + Assert.fail("FileNotFoundException expected with invalid JAR path"); + } catch(FileNotFoundException fnf) { + //pass + } catch(Exception ex) { + Assert.fail("FileNotFoundException expected with invalid JAR path, got: "+ex.toString()); + } + } + + @Test + public void deviceMapFactoryJarTest() throws Exception { + String test = "Mozilla/5.0 (Linux; U; Android 2.2; en; HTC Aria A6380 Build/ERE27) AppleWebKit/540.13+ (KHTML, like Gecko) Version/3.1 Mobile Safari/524.15.0"; + + Device device = DeviceMapFactory.getClient(LoaderOption.JAR).classifyDevice(test); + + Assert.assertEquals("test ua not htc aria", "HTC Aria", device.getId()); + + device = DeviceMapFactory.getClient(LoaderOption.JAR).classifyDevice(test); + + Assert.assertEquals("2nd test ua not htc aria", "HTC Aria", device.getId()); + } +} Added: devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientTest.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientTest.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientTest.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientTest.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,76 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collection; +import org.apache.devicemap.data.Device; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import org.apache.devicemap.loader.LoaderOption; + +@RunWith(value = Parameterized.class) +public class DeviceMapClientTest { + + private static DeviceMapClient client; + + @BeforeClass + public static void setupDeviceMapClient() throws Exception { + client = new DeviceMapClient(); + client.initDeviceData(LoaderOption.JAR); + } + + @Parameters + public static Collection<Object[]> data() throws Exception { + Collection<Object[]> params = new ArrayList<Object[]>(); + + BufferedReader reader = new BufferedReader(new InputStreamReader(DeviceMapClientTest.class.getResourceAsStream("/uas.data"))); + String line; + + while ((line = reader.readLine()) != null) { + params.add(line.split("\\|\\|")); + } + + reader.close(); + + return params; + } + + private final String testString; + private final String resultId; + + public DeviceMapClientTest(String testString, String resultId) { + this.testString = testString; + this.resultId = resultId; + } + + @Test + public void testDeviceMapClient() throws Exception { + Device device = client.classifyDevice(testString); + + Assert.assertEquals("classification failed for '" + testString + "'", resultId, device.getId()); + } +} Added: devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientUnitTest.java URL: http://svn.apache.org/viewvc/devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientUnitTest.java?rev=1717136&view=auto ============================================================================== --- devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientUnitTest.java (added) +++ devicemap/trunk/clients/1.0/java/client/src/test/java/org/apache/devicemap/DeviceMapClientUnitTest.java Sun Nov 29 23:36:18 2015 @@ -0,0 +1,84 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.devicemap; + +import org.junit.Assert; +import org.junit.Test; +import org.apache.devicemap.data.Device; + +public class DeviceMapClientUnitTest { + @Test + public void deviceMapClientUninitializedTest() throws Exception { + DeviceMapClient uninit = new DeviceMapClient(); + + try { + uninit.classifyDevice(""); + Assert.fail("Uninitialized device index exception expected"); + } catch (RuntimeException re) { + //pass + } catch (Exception ex) { + Assert.fail("Uninitialized device index exception expected, got: " + ex.toString()); + } + } + + @Test + public void deviceMapClientUnknownTest() throws Exception { + Device device = DeviceMapFactory.getClient().classifyDevice(""); + + Assert.assertEquals("test ua not unknown", Device.UNKNOWN_ID, device.getId()); + + device = DeviceMapFactory.getClient().classifyDevice(null); + + Assert.assertEquals("test ua not unknown", Device.UNKNOWN_ID, device.getId()); + } + + @Test + public void deviceMapClientMutateTest() throws Exception { + String test = "Mozilla/5.0 (Linux; U; Android 2.2; en; HTC Aria A6380 Build/ERE27) AppleWebKit/540.13+ (KHTML, like Gecko) Version/3.1 Mobile Safari/524.15.0"; + + Device device = DeviceMapFactory.getClient().classifyDevice(test); + + Assert.assertEquals("test ua not htc aria", "HTC Aria", device.getId()); + + try { + device.getAttributes().put("mutate", "true"); + Assert.fail("UnsupportedOperationException expected when changing result map"); + } catch (UnsupportedOperationException uoe) { + //pass + } catch (Exception ex) { + Assert.fail("UnsupportedOperationException expected when changing result map, got: " + ex.toString()); + } + } + + @Test + public void deviceMapClientMutateUnknownTest() throws Exception { + Device device = DeviceMapFactory.getClient().classifyDevice("unknown"); + + Assert.assertEquals("test ua not unknown", Device.UNKNOWN_ID, device.getId()); + + try { + device.getAttributes().put("mutate", "true"); + Assert.fail("UnsupportedOperationException expected when changing result map"); + } catch (UnsupportedOperationException uoe) { + //pass + } catch (Exception ex) { + Assert.fail("UnsupportedOperationException expected when changing result map, got: " + ex.toString()); + } + } +}
