XmlDataHandler.java

  1. /*******************************************************************************
  2.  * Copyright 2012 André Rouél
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *   http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  ******************************************************************************/
  16. package net.sf.uadetector.internal.data;

  17. import java.io.IOException;
  18. import java.io.InputStream;
  19. import java.io.InputStreamReader;

  20. import javax.annotation.Nonnull;

  21. import net.sf.qualitycheck.Check;
  22. import net.sf.uadetector.internal.data.domain.Browser;
  23. import net.sf.uadetector.internal.data.domain.BrowserOperatingSystemMapping;
  24. import net.sf.uadetector.internal.data.domain.BrowserPattern;
  25. import net.sf.uadetector.internal.data.domain.BrowserType;
  26. import net.sf.uadetector.internal.data.domain.Device;
  27. import net.sf.uadetector.internal.data.domain.DevicePattern;
  28. import net.sf.uadetector.internal.data.domain.OperatingSystem;
  29. import net.sf.uadetector.internal.data.domain.OperatingSystemPattern;
  30. import net.sf.uadetector.internal.data.domain.Robot;

  31. import org.slf4j.Logger;
  32. import org.slf4j.LoggerFactory;
  33. import org.xml.sax.Attributes;
  34. import org.xml.sax.InputSource;
  35. import org.xml.sax.SAXException;
  36. import org.xml.sax.SAXParseException;
  37. import org.xml.sax.helpers.DefaultHandler;

  38. public final class XmlDataHandler extends DefaultHandler {

  39.     public enum Tag {

  40.         /**
  41.          * Tag name of a browser entry
  42.          */
  43.         BROWSER("browser"),

  44.         /**
  45.          * Tag name of the ID of an browser pattern
  46.          */
  47.         BROWSER_ID("browser_id"),

  48.         /**
  49.          * Tag name of the informational URL of a browser entry
  50.          */
  51.         BROWSER_INFO_URL("browser_info_url"),

  52.         /**
  53.          * Tag name of a mapping entry between a browser and an operating system
  54.          */
  55.         BROWSER_OS_MAPPING("browser_os"),

  56.         /**
  57.          * Tag name of a browser pattern
  58.          */
  59.         BROWSER_PATTERN("browser_reg"),

  60.         /**
  61.          * Tag name of a browser type entry
  62.          */
  63.         BROWSER_TYPE("browser_type"),

  64.         /**
  65.          * Tag name of the type ID of a browser
  66.          */
  67.         BROWSER_TYPE_ID("type"),

  68.         /**
  69.          * Tag name of a producer company of an user agent
  70.          */
  71.         COMPANY("company"),

  72.         /**
  73.          * Tag name of the URL of a producer company from an user agent
  74.          */
  75.         COMPANY_URL("url_company"),

  76.         /**
  77.          * Tag name of a device
  78.          */
  79.         DEVICE("device"),

  80.         /**
  81.          * Tag name of a device pattern
  82.          */
  83.         DEVICE_ID("device_id"),

  84.         /**
  85.          * Tag name of the informational URL of an device entry
  86.          */
  87.         DEVICE_INFO_URL("device_info_url"),

  88.         /**
  89.          * Tag name of a device pattern
  90.          */
  91.         DEVICE_PATTERN("device_reg"),

  92.         /**
  93.          * Tag name of all devices
  94.          */
  95.         DEVICES("devices"),

  96.         /**
  97.          * Tag name of all device patterns
  98.          */
  99.         DEVICES_PATTERN("devices_reg"),

  100.         /**
  101.          * Tag name of an family of an user agent
  102.          */
  103.         FAMILY("family"),

  104.         /**
  105.          * Tag name of the icon of an entry
  106.          */
  107.         ICON("icon"),

  108.         /**
  109.          * Tag name of an ID of an user agent
  110.          */
  111.         ID("id"),

  112.         /**
  113.          * Tag name of the product name of an user agent
  114.          */
  115.         NAME("name"),

  116.         /**
  117.          * Tag name of an operating system entry
  118.          */
  119.         OPERATING_SYSTEM("os"),

  120.         /**
  121.          * Tag name of the ID of an operating system pattern
  122.          */
  123.         OPERATING_SYSTEM_ID("os_id"),

  124.         /**
  125.          * Tag name of the informational URL of an operating system entry
  126.          */
  127.         OPERATING_SYSTEM_INFO_URL("os_info_url"),

  128.         /**
  129.          * Tag name of an operating system pattern
  130.          */
  131.         OPERATING_SYSTEM_PATTERN("operating_system_reg"),

  132.         /**
  133.          * Tag name of the order of an user agent pattern
  134.          */
  135.         PATTERN_ORDER("order"),

  136.         /**
  137.          * Tag name of the regular expression of an user agent pattern
  138.          */
  139.         PATTERN_REGEX("regstring"),

  140.         /**
  141.          * Tag name of a robot entry
  142.          */
  143.         ROBOT("robot"),

  144.         /**
  145.          * Tag name of the informational URL of a robot entry
  146.          */
  147.         ROBOT_INFO_URL("bot_info_url"),

  148.         /**
  149.          * Tag name of the product URL of an user agent
  150.          */
  151.         URL("url"),

  152.         /**
  153.          * Tag name of an user agent string of a robot entry
  154.          */
  155.         USERAGENT("useragent"),

  156.         /**
  157.          * Tag name of the data version
  158.          */
  159.         VERSION("version");

  160.         public static Tag evaluate(@Nonnull final String tagName) {
  161.             Check.notNull(tagName, "tagName");

  162.             Tag result = null;
  163.             for (final Tag tag : values()) {
  164.                 if (tag.getTagName().equalsIgnoreCase(tagName)) {
  165.                     result = tag;
  166.                     break;
  167.                 }
  168.             }
  169.             return result;
  170.         }

  171.         public static boolean isBrowserOsMappingTag(final String tagName) {
  172.             return BROWSER_OS_MAPPING.getTagName().equalsIgnoreCase(tagName);
  173.         }

  174.         public static boolean isBrowserPatternTag(final String tagName) {
  175.             return BROWSER_PATTERN.getTagName().equalsIgnoreCase(tagName);
  176.         }

  177.         public static boolean isBrowserTag(final String tagName) {
  178.             return BROWSER.getTagName().equalsIgnoreCase(tagName);
  179.         }

  180.         public static boolean isBrowserTypeTag(final String tagName) {
  181.             return BROWSER_TYPE.getTagName().equalsIgnoreCase(tagName);
  182.         }

  183.         public static boolean isDevicePatternTag(final String tagName) {
  184.             return DEVICE_PATTERN.getTagName().equalsIgnoreCase(tagName);
  185.         }

  186.         public static boolean isDeviceTag(final String tagName) {
  187.             return DEVICE.getTagName().equalsIgnoreCase(tagName);
  188.         }

  189.         public static boolean isIdTag(final String tagName) {
  190.             return ID.getTagName().equalsIgnoreCase(tagName);
  191.         }

  192.         public static boolean isOperatingSystemPatternTag(final String tagName) {
  193.             return OPERATING_SYSTEM_PATTERN.getTagName().equalsIgnoreCase(tagName);
  194.         }

  195.         public static boolean isOperatingSystemTag(final String tagName) {
  196.             return OPERATING_SYSTEM.getTagName().equalsIgnoreCase(tagName);
  197.         }

  198.         public static boolean isRobotTag(final String tagName) {
  199.             return ROBOT.getTagName().equalsIgnoreCase(tagName);
  200.         }

  201.         @Nonnull
  202.         private String tagName;

  203.         private Tag(@Nonnull final String tagName) {
  204.             this.tagName = tagName;
  205.         }

  206.         @Nonnull
  207.         public String getTagName() {
  208.             return tagName;
  209.         }

  210.     }

  211.     /**
  212.      * Character set to read the internal Document Type Definition (DTD) of UAS data
  213.      */
  214.     private static final String CHARSET = "UTF-8";

  215.     /**
  216.      * Corresponding logger for this class
  217.      */
  218.     private static final Logger LOG = LoggerFactory.getLogger(XmlDataHandler.class);

  219.     /**
  220.      * Path to the internal Document Type Definition (DTD) of UAS data files to be able to work completely offline
  221.      */
  222.     protected static final String UASDATA_DEF = "uadetector/uasxmldata.dtd";

  223.     /**
  224.      * URL to the Document Type Definition (DTD) of UAS data files
  225.      */
  226.     protected static final String UASDATA_DEF_URL = "http://user-agent-string.info/rpc/uasxmldata.dtd";

  227.     /**
  228.      * Logs an issue while parsing XML.
  229.      *
  230.      * @param prefix
  231.      *            log level as string to add at the beginning of the message
  232.      * @param e
  233.      *            exception to log
  234.      */
  235.     protected static void logParsingIssue(final String prefix, final SAXParseException e) {
  236.         final StringBuilder buffer = new StringBuilder();
  237.         buffer.append(prefix);
  238.         buffer.append(" while reading UAS data: ");
  239.         buffer.append(e.getMessage());
  240.         buffer.append(" (line: ");
  241.         buffer.append(e.getLineNumber());
  242.         if (e.getSystemId() != null) {
  243.             buffer.append(" uri: ");
  244.             buffer.append(e.getSystemId());
  245.         }
  246.         buffer.append(")");
  247.         LOG.warn(buffer.toString());
  248.     }

  249.     private Browser.Builder browserBuilder = new Browser.Builder();

  250.     private Device.Builder deviceBuilder = new Device.Builder();

  251.     private BrowserOperatingSystemMapping.Builder browserOsMappingBuilder = new BrowserOperatingSystemMapping.Builder();

  252.     private BrowserPattern.Builder browserPatternBuilder = new BrowserPattern.Builder();

  253.     private DevicePattern.Builder devicePatternBuilder = new DevicePattern.Builder();

  254.     private BrowserType.Builder browserTypeBuilder = new BrowserType.Builder();

  255.     private StringBuilder buffer = new StringBuilder();

  256.     private Tag currentTag = null;

  257.     @Nonnull
  258.     private final DataBuilder dataBuilder;

  259.     /**
  260.      * Flag to note that a fatal error occurred while parsing the document
  261.      */
  262.     private boolean error = false;

  263.     private boolean isBrowser = false;

  264.     private boolean isBrowserOsMapping = false;

  265.     private boolean isBrowserPattern = false;

  266.     private boolean isBrowserType = false;

  267.     private boolean isDevice = false;

  268.     private boolean isDevicePattern = false;

  269.     private boolean isOperatingSystem = false;

  270.     private boolean isOperatingSystemPattern = false;

  271.     private boolean isRobot = false;

  272.     private OperatingSystem.Builder operatingSystemBuilder = new OperatingSystem.Builder();

  273.     private OperatingSystemPattern.Builder operatingSystemPatternBuilder = new OperatingSystemPattern.Builder();

  274.     private Robot.Builder robotBuilder = new Robot.Builder();

  275.     /**
  276.      * Flag to note that a warning occurred while parsing the document
  277.      */
  278.     private boolean warning = false;

  279.     public XmlDataHandler(@Nonnull final DataBuilder builder) {
  280.         Check.notNull(builder, "builder");

  281.         dataBuilder = builder;
  282.     }

  283.     private void addToBrowserBuilder() {
  284.         if (isBrowser) {
  285.             if (currentTag == Tag.ID) {
  286.                 browserBuilder.setId(buffer.toString());
  287.             } else if (currentTag == Tag.BROWSER_TYPE_ID) {
  288.                 browserBuilder.setTypeId(buffer.toString());
  289.             } else if (currentTag == Tag.NAME) {
  290.                 browserBuilder.setFamilyName(buffer.toString());
  291.             } else if (currentTag == Tag.URL) {
  292.                 browserBuilder.setUrl(buffer.toString());
  293.             } else if (currentTag == Tag.COMPANY) {
  294.                 browserBuilder.setProducer(buffer.toString());
  295.             } else if (currentTag == Tag.COMPANY_URL) {
  296.                 browserBuilder.setProducerUrl(buffer.toString());
  297.             } else if (currentTag == Tag.ICON) {
  298.                 browserBuilder.setIcon(buffer.toString());
  299.             } else if (currentTag == Tag.BROWSER_INFO_URL) {
  300.                 browserBuilder.setInfoUrl(buffer.toString());
  301.             }
  302.         }
  303.     }

  304.     private void addToBrowserOsMappingBuilder() {
  305.         if (isBrowserOsMapping && currentTag == Tag.BROWSER_ID) {
  306.             browserOsMappingBuilder.setBrowserId(buffer.toString());
  307.         } else if (isBrowserOsMapping && currentTag == Tag.OPERATING_SYSTEM_ID) {
  308.             browserOsMappingBuilder.setOperatingSystemId(buffer.toString());
  309.         }
  310.     }

  311.     private void addToBrowserPatternBuilder() {
  312.         if (isBrowserPattern && currentTag == Tag.PATTERN_ORDER) {
  313.             browserPatternBuilder.setPosition(buffer.toString());
  314.         } else if (isBrowserPattern && currentTag == Tag.BROWSER_ID) {
  315.             browserPatternBuilder.setId(buffer.toString());
  316.         } else if (isBrowserPattern && currentTag == Tag.PATTERN_REGEX) {
  317.             browserPatternBuilder.setPerlRegularExpression(buffer.toString());
  318.         }
  319.     }

  320.     private void addToBrowserTypeBuilder() {
  321.         if (isBrowserType && currentTag == Tag.ID) {
  322.             browserTypeBuilder.setId(buffer.toString());
  323.         } else if (isBrowserType && currentTag == Tag.BROWSER_TYPE_ID) {
  324.             browserTypeBuilder.setName(buffer.toString());
  325.         }
  326.     }

  327.     private void addToDeviceBuilder() {
  328.         if (isDevice) {
  329.             if (currentTag == Tag.ID) {
  330.                 deviceBuilder.setId(buffer.toString());
  331.             } else if (currentTag == Tag.NAME) {
  332.                 deviceBuilder.setName(buffer.toString());
  333.             } else if (currentTag == Tag.ICON) {
  334.                 deviceBuilder.setIcon(buffer.toString());
  335.             } else if (currentTag == Tag.DEVICE_INFO_URL) {
  336.                 deviceBuilder.setInfoUrl(buffer.toString());
  337.             }
  338.         }
  339.     }

  340.     private void addToDevicePatternBuilder() {
  341.         if (isDevicePattern && currentTag == Tag.PATTERN_ORDER) {
  342.             devicePatternBuilder.setPosition(buffer.toString());
  343.         } else if (isDevicePattern && currentTag == Tag.DEVICE_ID) {
  344.             devicePatternBuilder.setId(buffer.toString());
  345.         } else if (isDevicePattern && currentTag == Tag.PATTERN_REGEX) {
  346.             devicePatternBuilder.setPerlRegularExpression(buffer.toString());
  347.         }
  348.     }

  349.     private void addToOperatingSystemBuilder() {
  350.         if (isOperatingSystem) {
  351.             if (currentTag == Tag.ID) {
  352.                 operatingSystemBuilder.setId(buffer.toString());
  353.             } else if (currentTag == Tag.FAMILY) {
  354.                 operatingSystemBuilder.setFamily(buffer.toString());
  355.             } else if (currentTag == Tag.NAME) {
  356.                 operatingSystemBuilder.setName(buffer.toString());
  357.             } else if (currentTag == Tag.URL) {
  358.                 operatingSystemBuilder.setUrl(buffer.toString());
  359.             } else if (currentTag == Tag.COMPANY) {
  360.                 operatingSystemBuilder.setProducer(buffer.toString());
  361.             } else if (currentTag == Tag.COMPANY_URL) {
  362.                 operatingSystemBuilder.setProducerUrl(buffer.toString());
  363.             } else if (currentTag == Tag.ICON) {
  364.                 operatingSystemBuilder.setIcon(buffer.toString());
  365.             } else if (currentTag == Tag.OPERATING_SYSTEM_INFO_URL) {
  366.                 operatingSystemBuilder.setInfoUrl(buffer.toString());
  367.             }
  368.         }
  369.     }

  370.     private void addToOperatingSystemPatternBuilder() {
  371.         if (isOperatingSystemPattern) {
  372.             if (currentTag == Tag.PATTERN_ORDER) {
  373.                 operatingSystemPatternBuilder.setPosition(buffer.toString());
  374.             } else if (currentTag == Tag.OPERATING_SYSTEM_ID) {
  375.                 operatingSystemPatternBuilder.setId(buffer.toString());
  376.             } else if (currentTag == Tag.PATTERN_REGEX) {
  377.                 operatingSystemPatternBuilder.setPerlRegularExpression(buffer.toString());
  378.             }
  379.         }
  380.     }

  381.     private void addToRobotBuilder() {
  382.         if (isRobot) {
  383.             if (currentTag == Tag.ID) {
  384.                 robotBuilder.setId(buffer.toString());
  385.             } else if (currentTag == Tag.USERAGENT) {
  386.                 robotBuilder.setUserAgentString(buffer.toString());
  387.             } else if (currentTag == Tag.FAMILY) {
  388.                 robotBuilder.setFamilyName(buffer.toString());
  389.             } else if (currentTag == Tag.NAME) {
  390.                 robotBuilder.setName(buffer.toString());
  391.             } else if (currentTag == Tag.COMPANY) {
  392.                 robotBuilder.setProducer(buffer.toString());
  393.             } else if (currentTag == Tag.COMPANY_URL) {
  394.                 robotBuilder.setProducerUrl(buffer.toString());
  395.             } else if (currentTag == Tag.ICON) {
  396.                 robotBuilder.setIcon(buffer.toString());
  397.             } else if (currentTag == Tag.ROBOT_INFO_URL) {
  398.                 robotBuilder.setInfoUrl(buffer.toString());
  399.             }
  400.         }
  401.     }

  402.     @Override
  403.     public void characters(final char ch[], final int start, final int length) throws SAXException {
  404.         buffer.append(new String(ch, start, length));
  405.     }

  406.     @Override
  407.     public void endElement(final String uri, final String localName, final String tagName) throws SAXException {

  408.         transferToSpecificBuilderAndReset();

  409.         if (Tag.isRobotTag(tagName)) {
  410.             saveAndResetRobotBuilder();
  411.             isRobot = false;
  412.         } else if (Tag.isBrowserTag(tagName)) {
  413.             saveAndResetBrowserBuilder();
  414.             isBrowser = false;
  415.         } else if (Tag.isOperatingSystemTag(tagName)) {
  416.             saveAndResetOperatingSystemBuilder();
  417.             isOperatingSystem = false;
  418.         } else if (Tag.isBrowserTypeTag(tagName)) {
  419.             saveAndResetBrowserTypeBuilder();
  420.             isBrowserType = false;
  421.         } else if (Tag.isBrowserPatternTag(tagName)) {
  422.             saveAndResetBrowserPatternBuilder();
  423.             isBrowserPattern = false;
  424.         } else if (Tag.isBrowserOsMappingTag(tagName)) {
  425.             saveAndResetBrowserOperatingSystemMapping();
  426.             isBrowserOsMapping = false;
  427.         } else if (Tag.isOperatingSystemPatternTag(tagName)) {
  428.             saveAndResetOperatingSystemPatternBuilder();
  429.             isOperatingSystemPattern = false;
  430.         } else if (Tag.isDeviceTag(tagName)) {
  431.             saveAndResetDeviceBuilder();
  432.             isDevice = false;
  433.         } else if (Tag.isDevicePatternTag(tagName)) {
  434.             saveAndResetDevicePatternBuilder();
  435.             isDevicePattern = false;
  436.         }

  437.         currentTag = null;
  438.     }

  439.     @Override
  440.     public void error(final SAXParseException e) throws SAXException {
  441.         error = true;
  442.         logParsingIssue("Error", e);
  443.         super.fatalError(e);
  444.     }

  445.     @Override
  446.     public void fatalError(final SAXParseException e) throws SAXException {
  447.         logParsingIssue("Fatal error", e);

  448.         // this call throws a SAXException
  449.         super.fatalError(e);
  450.     }

  451.     /**
  452.      * Gets the flag whether an error occurred while parsing the document.
  453.      *
  454.      * @return {@code true} if an error occurred otherwise {@code false}
  455.      */
  456.     public boolean hasError() {
  457.         return error;
  458.     }

  459.     /**
  460.      * Gets the flag whether an warning occurred while parsing the document.
  461.      *
  462.      * @return {@code true} if an warning occurred otherwise {@code false}
  463.      */
  464.     public boolean hasWarning() {
  465.         return warning;
  466.     }

  467.     @Override
  468.     public InputSource resolveEntity(final String publicId, final String systemId) throws IOException, SAXException {
  469.         if (UASDATA_DEF_URL.equals(systemId)) {
  470.             final InputStream stream = this.getClass().getClassLoader().getResourceAsStream(UASDATA_DEF);
  471.             return new InputSource(new InputStreamReader(stream, CHARSET));
  472.         }
  473.         throw new SAXException("unable to resolve remote entity, systemId = " + systemId);
  474.     }

  475.     private void saveAndResetBrowserBuilder() {
  476.         dataBuilder.appendBrowserBuilder(browserBuilder);
  477.         browserBuilder = new Browser.Builder();
  478.     }

  479.     private void saveAndResetBrowserOperatingSystemMapping() {
  480.         dataBuilder.appendBrowserOperatingSystemMapping(browserOsMappingBuilder.build());
  481.         browserOsMappingBuilder = new BrowserOperatingSystemMapping.Builder();
  482.     }

  483.     private void saveAndResetBrowserPatternBuilder() {
  484.         try {
  485.             dataBuilder.appendBrowserPattern(browserPatternBuilder.build());
  486.         } catch (final IllegalArgumentException e) {
  487.             LOG.warn("Can not append browser pattern: " + e.getLocalizedMessage());
  488.         }
  489.         browserPatternBuilder = new BrowserPattern.Builder();
  490.     }

  491.     private void saveAndResetBrowserTypeBuilder() {
  492.         dataBuilder.appendBrowserType(browserTypeBuilder.build());
  493.         browserTypeBuilder = new BrowserType.Builder();
  494.     }

  495.     private void saveAndResetDeviceBuilder() {
  496.         dataBuilder.appendDeviceBuilder(deviceBuilder);
  497.         deviceBuilder = new Device.Builder();
  498.     }

  499.     private void saveAndResetDevicePatternBuilder() {
  500.         try {
  501.             dataBuilder.appendDevicePattern(devicePatternBuilder.build());
  502.         } catch (final IllegalArgumentException e) {
  503.             LOG.warn("Can not append device pattern: " + e.getLocalizedMessage());
  504.         }
  505.         devicePatternBuilder = new DevicePattern.Builder();
  506.     }

  507.     private void saveAndResetOperatingSystemBuilder() {
  508.         dataBuilder.appendOperatingSystemBuilder(operatingSystemBuilder);
  509.         operatingSystemBuilder = new OperatingSystem.Builder();
  510.     }

  511.     private void saveAndResetOperatingSystemPatternBuilder() {
  512.         try {
  513.             dataBuilder.appendOperatingSystemPattern(operatingSystemPatternBuilder.build());
  514.         } catch (final IllegalArgumentException e) {
  515.             LOG.warn("Can not append OS pattern: " + e.getLocalizedMessage());
  516.         }
  517.         operatingSystemPatternBuilder = new OperatingSystemPattern.Builder();
  518.     }

  519.     private void saveAndResetRobotBuilder() {
  520.         dataBuilder.appendRobot(robotBuilder.build());
  521.         robotBuilder = new Robot.Builder();
  522.     }

  523.     @Override
  524.     public void startElement(final String uri, final String localName, final String tagName, final Attributes attributes)
  525.             throws SAXException {

  526.         if (Tag.isRobotTag(tagName)) {
  527.             isRobot = true;
  528.         } else if (Tag.isBrowserTag(tagName)) {
  529.             isBrowser = true;
  530.         } else if (Tag.isOperatingSystemTag(tagName)) {
  531.             isOperatingSystem = true;
  532.         } else if (Tag.isBrowserTypeTag(tagName)) {
  533.             isBrowserType = true;
  534.         } else if (Tag.isBrowserPatternTag(tagName)) {
  535.             isBrowserPattern = true;
  536.         } else if (Tag.isBrowserOsMappingTag(tagName)) {
  537.             isBrowserOsMapping = true;
  538.         } else if (Tag.isOperatingSystemPatternTag(tagName)) {
  539.             isOperatingSystemPattern = true;
  540.         } else if (Tag.isDeviceTag(tagName)) {
  541.             isDevice = true;
  542.         } else if (Tag.isDevicePatternTag(tagName)) {
  543.             isDevicePattern = true;
  544.         }

  545.         currentTag = Tag.evaluate(tagName);
  546.     }

  547.     /**
  548.      * Transfers all characters of a specific tag to the corresponding builder and resets the string buffer.
  549.      */
  550.     private void transferToSpecificBuilderAndReset() {

  551.         // version
  552.         if (currentTag == Tag.VERSION) {
  553.             dataBuilder.setVersion(buffer.toString());
  554.         }

  555.         // robot browser
  556.         addToRobotBuilder();

  557.         // build browser
  558.         addToBrowserBuilder();

  559.         // build operating system
  560.         addToOperatingSystemBuilder();

  561.         // build browser pattern
  562.         addToBrowserPatternBuilder();

  563.         // build browser type
  564.         addToBrowserTypeBuilder();

  565.         // build browser to operating system mapping
  566.         addToBrowserOsMappingBuilder();

  567.         // build operating system pattern
  568.         addToOperatingSystemPatternBuilder();

  569.         // build browser
  570.         addToDeviceBuilder();

  571.         // build browser pattern
  572.         addToDevicePatternBuilder();

  573.         buffer = new StringBuilder();
  574.     }

  575.     @Override
  576.     public void warning(final SAXParseException e) throws SAXException {
  577.         warning = true;
  578.         logParsingIssue("Warning", e);
  579.         super.warning(e);
  580.     }

  581. }