/* * Copyright 2013 Skynav, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY SKYNAV, INC. AND ITS CONTRIBUTORS “AS IS” AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL SKYNAV, INC. OR ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.skynav.ttv.util; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.bind.JAXBElement; import javax.xml.namespace.QName; import org.w3c.dom.Attr; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.xml.sax.Locator; import org.xml.sax.helpers.LocatorImpl; public class Locators { private static final QName locatorQName = new QName(Annotations.getNamespace(), "loc", Annotations.getNamespacePrefix()); public static QName getLocatorAttributeQName() { return locatorQName; } public static Locator getLocator(String sysid) { LocatorImpl locator = new LocatorImpl(); locator.setSystemId(sysid); return locator; } public static Locator getLocator(Object content, String sysid) { if (content instanceof JAXBElement<?>) return getLocator(((JAXBElement<?>) content).getValue(), sysid); else return getLocatorAttributeAsLocator(content, sysid); } private static final Pattern locPattern = Pattern.compile("\\{([^\\}]*)\\}:([-]?\\d+):([-]?\\d+)"); private static Locator getLocatorAttributeAsLocator(Object content, String sysid) { String locatorAttribute = getLocatorAttribute(content); if (locatorAttribute != null) { Matcher m = locPattern.matcher(locatorAttribute); if (m.matches()) { LocatorImpl locator = new LocatorImpl(); assert m.groupCount() == 3; String sid = m.group(1); if ((sid == null) || sid.isEmpty()) sid = sysid; locator.setSystemId(sid); locator.setLineNumber(Integer.parseInt(m.group(2))); locator.setColumnNumber(Integer.parseInt(m.group(3))); return locator; } else return null; } else return null; } private static String getLocatorAttribute(Object content) { Map<QName,String> attrs = Annotations.getOtherAttributes(content); if ((attrs != null) && attrs.containsKey(getLocatorAttributeQName())) return attrs.get(getLocatorAttributeQName()); else if (content instanceof Element) return getLocatorAttribute((Element) content); else return null; } private static String getLocatorAttribute(Element element) { NamedNodeMap attributes = element.getAttributes(); for (int i = 0, n = attributes.getLength(); i < n; ++i) { Node item = attributes.item(i); if (!(item instanceof Attr)) continue; Attr attribute = (Attr) item; String nsUri = attribute.getNamespaceURI(); String localName = attribute.getLocalName(); if (localName == null) localName = attribute.getName(); if (localName.indexOf("xmlns") == 0) continue; QName name = new QName(nsUri != null ? nsUri : "", localName); if (name.equals(getLocatorAttributeQName())) return attribute.getValue(); } return null; } }