The device detection data file contains meta data that can provide additional information about the various records in the data model. This example shows how to access this data and display the values available.
To help navigate the data, it's useful to have an understanding of the types of records that are present:
The example will output each component in turn, with a list of the properties associated with each component. Some of the possible values for each property are also displayed. There are too many profiles to display, so we just list the number of profiles for each component.
Finally, the evidence keys that are accepted by device detection are listed. These are the keys that, when added to the evidence collection in flow data, could have some impact on the result returned by device detection.
package fiftyone.devicedetection.examples.console;
import fiftyone.devicedetection.examples.shared.DataFileHelper;
import fiftyone.devicedetection.hash.engine.onpremise.flowelements.DeviceDetectionHashEngine;
import fiftyone.devicedetection.hash.engine.onpremise.flowelements.DeviceDetectionHashEngineBuilder;
import fiftyone.pipeline.core.data.EvidenceKeyFilterWhitelist;
import fiftyone.pipeline.engines.Constants;
import fiftyone.pipeline.engines.fiftyone.data.ComponentMetaData;
import fiftyone.pipeline.engines.fiftyone.data.ProfileMetaData;
import fiftyone.pipeline.engines.fiftyone.data.ValueMetaData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import static fiftyone.common.testhelpers.LogbackHelper.configureLogback;
import static fiftyone.pipeline.util.FileFinder.getFilePath;
public class MetadataOnPrem {
private static final Logger logger = LoggerFactory.getLogger(GettingStartedOnPrem.class);
public static String LITE_V_4_1_HASH = "51Degrees-LiteV4.1.hash";
public static void main(String[] args) throws Exception {
configureLogback(getFilePath("logback.xml"));
String dataFile = args.length > 0 ? args[0] : LITE_V_4_1_HASH;
run(dataFile, System.out);
}
public static void run(String dataFile, OutputStream output) throws Exception {
logger.info("Running MetadataOnPrem example");
String dataFileLocation;
try {
dataFileLocation = getFilePath(dataFile).getAbsolutePath();
} catch (Exception e) {
DataFileHelper.cantFindDataFile(dataFile);
throw e;
}
try (DeviceDetectionHashEngine ddEngine =
new DeviceDetectionHashEngineBuilder(LoggerFactory.getILoggerFactory())
.setPerformanceProfile(Constants.PerformanceProfiles.LowMemory)
.setAutoUpdate(false)
.setDataFileSystemWatcher(false)
.setDataUpdateOnStartup(false)
.build(dataFileLocation, false)){
PrintWriter writer = new PrintWriter(output);
logger.info("Listing Components");
outputComponents(ddEngine, writer);
writer.println();
writer.flush();
logger.info("Listing Profile Details");
outputProfileDetails(ddEngine, writer);
writer.println();
writer.flush();
logger.info("Listing Evidence Key Details");
outputEvidenceKeyDetails(ddEngine, writer);
writer.println();
writer.flush();
DataFileHelper.logDataFileInfo(ddEngine);
}
}
private static void outputEvidenceKeyDetails(DeviceDetectionHashEngine ddEngine,
PrintWriter output){
output.println();
if (ddEngine.getEvidenceKeyFilter() instanceof EvidenceKeyFilterWhitelist) {
EvidenceKeyFilterWhitelist filter = (EvidenceKeyFilterWhitelist) ddEngine.getEvidenceKeyFilter();
output.println("Accepted evidence keys:");
for (Map.Entry<String, Integer> entry : filter.getWhitelist().entrySet()){
output.println("\t" + entry.getKey());
}
} else {
output.format("The evidence key filter has type " +
"%s. As this does not extend " +
"EvidenceKeyFilterWhitelist, a list of accepted values cannot be " +
"displayed. As an alternative, you can pass evidence keys to " +
"filter.include(string) to see if a particular key will be included " +
"or not.\n", ddEngine.getEvidenceKeyFilter().getClass().getName());
output.println("For example, header.user-agent " +
(ddEngine.getEvidenceKeyFilter().include("header.user-agent") ?
"is " : "is not ") + "accepted.");
}
}
private static void outputProfileDetails(DeviceDetectionHashEngine ddEngine,
PrintWriter output) {
Map<String, List<ProfileMetaData>> groups =
StreamSupport.stream(ddEngine.getProfiles().spliterator(), false)
.collect(Collectors.groupingBy(p -> p.getComponent().getName()));
groups.forEach((k,v)->output.format("%s Profiles: %d\n", k , v.size()));
}
private static void outputComponents(DeviceDetectionHashEngine ddEngine, PrintWriter output){
ddEngine.getComponents().forEach(c -> {
output.println("Component - "+ c.getName());
outputProperties(c, output);
});
}
private static void outputProperties(ComponentMetaData component, PrintWriter output) {
if (component.getProperties().iterator().hasNext() == false) {
output.println(" ... no properties");
return;
}
component.getProperties()
.forEach(property-> {
output.format(" Property - %s [Category: %s] (%s)\n " +
"Description: %s\n",
property.getName(),
property.getCategory(),
property.getType().getName(),
property.getDescription());
if (property.getCategory().equals("Device Metrics")==false) {
StringBuilder values = new StringBuilder(" Possible " +
"values: ");
Spliterator<ValueMetaData> spliterator2 =
property.getValues().spliterator();
StreamSupport.stream(spliterator2, false)
.limit(20)
.forEach(value -> {
values.append(truncateToNl(value.getName()));
String d = value.getDescription();
if (Objects.nonNull(d) && d.isEmpty() == false) {
values.append("(")
.append(d)
.append(")");
}
values.append(",");
});
if (spliterator2.estimateSize() > 20) {
values.append(" + more ...");
}
output.println(values);
}
});
}
private static String truncateToNl(String text) {
String[] lines = text.split("\n");
Optional<String> result = Arrays.stream(lines).filter(s -> !s.isEmpty()).findFirst();
return result.orElse("[empty]") + (lines.length > 1 ? "..." : "");
}
}