/******************************************************************************* * Copyright 2012 André Rouél * * Licensed 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 net.sf.uadetector.internal.data; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; import java.util.concurrent.atomic.AtomicInteger; import javax.annotation.Nonnull; import javax.annotation.concurrent.Immutable; import net.sf.qualitycheck.Check; import net.sf.uadetector.internal.data.domain.Browser; import net.sf.uadetector.internal.data.domain.BrowserOperatingSystemMapping; import net.sf.uadetector.internal.data.domain.BrowserPattern; import net.sf.uadetector.internal.data.domain.BrowserType; import net.sf.uadetector.internal.data.domain.Device; import net.sf.uadetector.internal.data.domain.DevicePattern; import net.sf.uadetector.internal.data.domain.OperatingSystem; import net.sf.uadetector.internal.data.domain.OperatingSystemPattern; import net.sf.uadetector.internal.data.domain.Robot; /** * This class represents the detection information of <i>UADetector</i>. * <p> * An instance of {@code Data} is immutable, their values cannot be changed after creation. * * @author André Rouél */ @Immutable public class Data implements Serializable { /** * An <i>immutable</i> empty {@code Data} object. */ public static final Data EMPTY = new Data(new HashSet<Browser>(0), new HashMap<Integer, SortedSet<BrowserPattern>>(0), new HashMap<Integer, BrowserType>(0), new TreeMap<BrowserPattern, Browser>(), new HashSet<BrowserOperatingSystemMapping>(0), new HashSet<OperatingSystem>(0), new HashMap<Integer, SortedSet<OperatingSystemPattern>>(0), new TreeMap<OperatingSystemPattern, OperatingSystem>(), new ArrayList<Robot>(0), new HashSet<Device>(0), new HashMap<Integer, SortedSet<DevicePattern>>(0), new TreeMap<DevicePattern, Device>(), ""); private static final long serialVersionUID = 8522012551928801089L; @Nonnull private final Map<Integer, SortedSet<BrowserPattern>> browserPatterns; @Nonnull private final Set<Browser> browsers; @Nonnull private final Map<Integer, SortedSet<DevicePattern>> devicePatterns; @Nonnull private final Set<Device> devices; @Nonnull private final SortedMap<DevicePattern, Device> patternToDeviceMap; @Nonnull private final Set<BrowserOperatingSystemMapping> browserToOperatingSystemMappings; @Nonnull private final Map<Integer, BrowserType> browserTypes; @Nonnull private final Map<Integer, SortedSet<OperatingSystemPattern>> operatingSystemPatterns; @Nonnull private final Set<OperatingSystem> operatingSystems; @Nonnull private final SortedMap<BrowserPattern, Browser> patternToBrowserMap; @Nonnull private final SortedMap<OperatingSystemPattern, OperatingSystem> patternToOperatingSystemMap; @Nonnull private final List<Robot> robots; /** * Version information of the UAS data */ @Nonnull private final String version; public Data(@Nonnull final Set<Browser> browsers, @Nonnull final Map<Integer, SortedSet<BrowserPattern>> browserPatterns, @Nonnull final Map<Integer, BrowserType> browserTypes, @Nonnull final SortedMap<BrowserPattern, Browser> patternToBrowserMap, @Nonnull final Set<BrowserOperatingSystemMapping> browserToOperatingSystemMappings, @Nonnull final Set<OperatingSystem> operatingSystems, @Nonnull final Map<Integer, SortedSet<OperatingSystemPattern>> operatingSystemPatterns, @Nonnull final SortedMap<OperatingSystemPattern, OperatingSystem> patternToOperatingSystemMap, @Nonnull final List<Robot> robots, @Nonnull final Set<Device> devices, @Nonnull final Map<Integer, SortedSet<DevicePattern>> devicePatterns, @Nonnull final SortedMap<DevicePattern, Device> patternToDeviceMap, @Nonnull final String version) { Check.notNull(browsers, "browsers"); Check.notNull(browserPatterns, "browserPatterns"); Check.notNull(browserTypes, "browserTypes"); Check.notNull(patternToBrowserMap, "patternToBrowserMap"); Check.notNull(browserToOperatingSystemMappings, "browserToOperatingSystemMap"); Check.notNull(operatingSystems, "operatingSystems"); Check.notNull(operatingSystemPatterns, "operatingSystemPatterns"); Check.notNull(patternToOperatingSystemMap, "patternToOperatingSystemMap"); Check.notNull(robots, "robots"); Check.notNull(devices, "devices"); Check.notNull(devicePatterns, "devicePatterns"); Check.notNull(patternToDeviceMap, "patternToDeviceMap"); Check.notNull(version, "version"); this.browsers = Collections.unmodifiableSet(new HashSet<Browser>(browsers)); this.browserPatterns = Collections.unmodifiableMap(new HashMap<Integer, SortedSet<BrowserPattern>>(browserPatterns)); this.browserTypes = Collections.unmodifiableMap(new HashMap<Integer, BrowserType>(Check.notNull(browserTypes, "browserTypes"))); this.patternToBrowserMap = Collections.unmodifiableSortedMap(new TreeMap<BrowserPattern, Browser>(patternToBrowserMap)); this.browserToOperatingSystemMappings = Collections.unmodifiableSet(new HashSet<BrowserOperatingSystemMapping>( browserToOperatingSystemMappings)); this.operatingSystems = Collections.unmodifiableSet(new HashSet<OperatingSystem>(operatingSystems)); this.operatingSystemPatterns = Collections.unmodifiableMap(new HashMap<Integer, SortedSet<OperatingSystemPattern>>( operatingSystemPatterns)); this.patternToOperatingSystemMap = Collections.unmodifiableSortedMap(new TreeMap<OperatingSystemPattern, OperatingSystem>( patternToOperatingSystemMap)); this.robots = Collections.unmodifiableList(new ArrayList<Robot>(robots)); this.devices = Collections.unmodifiableSet(new HashSet<Device>(devices)); this.devicePatterns = Collections.unmodifiableMap(new HashMap<Integer, SortedSet<DevicePattern>>(devicePatterns)); this.patternToDeviceMap = Collections.unmodifiableSortedMap(new TreeMap<DevicePattern, Device>(patternToDeviceMap)); this.version = Check.notNull(version, "version"); } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Data other = (Data) obj; if (!browsers.equals(other.browsers)) { return false; } if (!browserPatterns.equals(other.browserPatterns)) { return false; } if (!browserTypes.equals(other.browserTypes)) { return false; } if (!patternToBrowserMap.equals(other.patternToBrowserMap)) { return false; } if (!browserToOperatingSystemMappings.equals(other.browserToOperatingSystemMappings)) { return false; } if (!operatingSystems.equals(other.operatingSystems)) { return false; } if (!operatingSystemPatterns.equals(other.operatingSystemPatterns)) { return false; } if (!patternToOperatingSystemMap.equals(other.patternToOperatingSystemMap)) { return false; } if (!robots.equals(other.robots)) { return false; } if (!devices.equals(other.devices)) { return false; } if (!devicePatterns.equals(other.devicePatterns)) { return false; } if (!patternToDeviceMap.equals(other.patternToDeviceMap)) { return false; } if (!version.equals(other.version)) { return false; } return true; } @Nonnull public Map<Integer, SortedSet<BrowserPattern>> getBrowserPatterns() { return browserPatterns; } @Nonnull public Set<Browser> getBrowsers() { return browsers; } @Nonnull public Set<BrowserOperatingSystemMapping> getBrowserToOperatingSystemMappings() { return browserToOperatingSystemMappings; } @Nonnull public Map<Integer, BrowserType> getBrowserTypes() { return browserTypes; } @Nonnull public Map<Integer, SortedSet<DevicePattern>> getDevicePatterns() { return devicePatterns; } @Nonnull public Set<Device> getDevices() { return devices; } @Nonnull public Map<Integer, SortedSet<OperatingSystemPattern>> getOperatingSystemPatterns() { return operatingSystemPatterns; } @Nonnull public Set<OperatingSystem> getOperatingSystems() { return operatingSystems; } @Nonnull public SortedMap<BrowserPattern, Browser> getPatternToBrowserMap() { return patternToBrowserMap; } @Nonnull public SortedMap<DevicePattern, Device> getPatternToDeviceMap() { return patternToDeviceMap; } @Nonnull public SortedMap<OperatingSystemPattern, OperatingSystem> getPatternToOperatingSystemMap() { return patternToOperatingSystemMap; } @Nonnull public List<Robot> getRobots() { return robots; } /** * Gets the version of the UAS data which are available within this instance. * * @return version of UAS data */ @Nonnull public String getVersion() { return version; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + browsers.hashCode(); result = prime * result + browserPatterns.hashCode(); result = prime * result + browserTypes.hashCode(); result = prime * result + patternToBrowserMap.hashCode(); result = prime * result + browserToOperatingSystemMappings.hashCode(); result = prime * result + operatingSystems.hashCode(); result = prime * result + operatingSystemPatterns.hashCode(); result = prime * result + patternToOperatingSystemMap.hashCode(); result = prime * result + robots.hashCode(); result = prime * result + devices.hashCode(); result = prime * result + devicePatterns.hashCode(); result = prime * result + patternToDeviceMap.hashCode(); result = prime * result + version.hashCode(); return result; } @Nonnull public String toStats() { final StringBuilder builder = new StringBuilder(); builder.append("UAS data stats\n"); builder.append("----------------------------------------------------------------"); builder.append('\n'); builder.append("version:\t\t"); builder.append(version); builder.append('\n'); builder.append("browser:\t\t"); builder.append(browsers.size()); builder.append('\n'); final Map<String, AtomicInteger> browserByType = new HashMap<String, AtomicInteger>(); for (final Browser browser : browsers) { final AtomicInteger counter = browserByType.get(browser.getType().getName()); if (counter == null) { browserByType.put(browser.getType().getName(), new AtomicInteger(1)); } else { counter.incrementAndGet(); } } for (final Entry<String, AtomicInteger> entry : browserByType.entrySet()) { builder.append('\t'); builder.append('\t'); builder.append('\t'); builder.append(entry.getKey()); builder.append(":\t"); builder.append(entry.getValue().get()); builder.append('\n'); } builder.append("browser patterns:\t"); builder.append(patternToBrowserMap.size()); builder.append('\n'); builder.append("operating systems:\t"); builder.append(operatingSystems.size()); builder.append('\n'); builder.append("os patterns:\t\t"); builder.append(patternToOperatingSystemMap.size()); builder.append('\n'); builder.append("robots:\t\t\t"); builder.append(robots.size()); builder.append('\n'); builder.append("devices:\t"); builder.append(devices.size()); builder.append('\n'); builder.append("device patterns:\t"); builder.append(patternToDeviceMap.size()); builder.append('\n'); builder.append("----------------------------------------------------------------"); return builder.toString(); } @Override public String toString() { final StringBuilder builder = new StringBuilder(); builder.append("Data [browsers="); builder.append(browsers); builder.append(", browserPatterns="); builder.append(browserPatterns); builder.append(", browserTypes="); builder.append(browserTypes); builder.append(", patternToBrowserMap="); builder.append(patternToBrowserMap); builder.append(", browserToOperatingSystemMap="); builder.append(browserToOperatingSystemMappings); builder.append(", operatingSystems="); builder.append(operatingSystems); builder.append(", operatingSystemPatterns="); builder.append(operatingSystemPatterns); builder.append(", patternToOperatingSystemMap="); builder.append(patternToOperatingSystemMap); builder.append(", robots="); builder.append(robots); builder.append(", devices="); builder.append(devices); builder.append(", devicePatterns="); builder.append(devicePatterns); builder.append(", patternToDeviceMap="); builder.append(patternToDeviceMap); builder.append(", version="); builder.append(version); builder.append("]"); return builder.toString(); } }