import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.opendaylight.yangtools.concepts.Immutable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.opendaylight.yangtools.yang.common.QName;
/**
* The QName from XML consists of local name of element and XML namespace, but
};
};
+ static final String QNAME_REVISION_DELIMITER = "?revision=";
+ static final String QNAME_LEFT_PARENTHESIS = "(";
+ static final String QNAME_RIGHT_PARENTHESIS = ")";
+
+ //Nullable
private final URI namespace;
+ //Mandatory
private final String localName;
+ //Nullable
private final String prefix;
+ //Nullable
private final String formattedRevision;
+ //Nullable
private final Date revision;
/**
* YANG schema identifier
*/
public QName(URI namespace, Date revision, String prefix, String localName) {
+ this.localName = checkLocalName(localName);
this.namespace = namespace;
- this.localName = localName;
this.revision = revision;
this.prefix = prefix;
if(revision != null) {
this(namespace, null, "", localName);
}
+ private static String checkLocalName(String localName) {
+ if (localName == null || localName.length() == 0) {
+ throw new IllegalArgumentException("Parameter 'localName' must be non empty string.");
+ }
+ String [] illegalSubstrings = new String[] {"?", "(", ")", "&"};
+ for(String illegalSubstring: illegalSubstrings) {
+ if (localName.contains(illegalSubstring)) {
+ throw new IllegalArgumentException(String.format(
+ "Parameter 'localName':'%s' contains illegal sequence '%s'",
+ localName, illegalSubstring));
+ }
+ }
+ return localName;
+ }
+
/**
* QName Constructor.
*
this(base.getNamespace(), base.getRevision(), base.getPrefix(), localName);
}
- // TODO: rework with pattern
- public QName(String base) throws ParseException {
+ /**
+ * @deprecated Use {@link #create(String)} instead.
+ * This implementation is broken.
+ */
+ @Deprecated
+ public QName(String input) throws ParseException {
Date revision = null;
- String nsAndRev = base.substring(base.indexOf("(") + 1, base.indexOf(")"));
+ String nsAndRev = input.substring(input.indexOf("(") + 1, input.indexOf(")"));
if (nsAndRev.contains("?")) {
String[] splitted = nsAndRev.split("\\?");
this.namespace = URI.create(splitted[0]);
this.namespace = URI.create(nsAndRev);
}
- this.localName = base.substring(base.indexOf(")") + 1);
+ this.localName = checkLocalName(input.substring(input.indexOf(")") + 1));
this.revision = revision;
this.prefix = null;
if (revision != null) {
}
}
+
+ private static Pattern QNAME_PATTERN_FULL = Pattern.compile(
+ "^\\((.+)\\" + QNAME_REVISION_DELIMITER + "(.+)\\)(.+)$");
+ private static Pattern QNAME_PATTERN_NO_REVISION = Pattern.compile(
+ "^\\((.+)\\)(.+)$" );
+ private static Pattern QNAME_PATTERN_NO_NAMESPACE_NO_REVISION = Pattern.compile(
+ "^(.+)$" );
+
+ public static QName create(String input) {
+ Matcher matcher = QNAME_PATTERN_FULL.matcher(input);
+ if (matcher.matches()) {
+ String namespace = matcher.group(1);
+ String revision = matcher.group(2);
+ String localName = matcher.group(3);
+ return create(namespace, revision, localName);
+ }
+ matcher = QNAME_PATTERN_NO_REVISION.matcher(input);
+ if (matcher.matches()) {
+ URI namespace = URI.create(matcher.group(1));
+ String localName = matcher.group(2);
+ return new QName(namespace, localName);
+ }
+ matcher = QNAME_PATTERN_NO_NAMESPACE_NO_REVISION.matcher(input);
+ if (matcher.matches()) {
+ String localName = matcher.group(1);
+ return new QName((URI)null, localName);
+ }
+ throw new IllegalArgumentException("Invalid input:" + input);
+ }
+
/**
* Returns XMLNamespace assigned to the YANG module.
*
public String toString() {
StringBuilder sb = new StringBuilder();
if (namespace != null) {
- sb.append("(" + namespace);
+ sb.append(QNAME_LEFT_PARENTHESIS + namespace);
if (revision != null) {
- sb.append("?revision=" + REVISION_FORMAT.get().format(revision));
+ sb.append(QNAME_REVISION_DELIMITER + REVISION_FORMAT.get().format(revision));
}
- sb.append(")");
+ sb.append(QNAME_RIGHT_PARENTHESIS);
}
sb.append(localName);
return sb.toString();
public static Date parseRevision(String formatedDate) {
try {
return REVISION_FORMAT.get().parse(formatedDate);
- } catch (ParseException e) {
- throw new IllegalArgumentException("Revision is not in supported format",e);
+ } catch (ParseException| RuntimeException e) {
+ throw new IllegalArgumentException("Revision is not in supported format:" + formatedDate,e);
}
}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.common;
+
+import org.junit.Test;
+
+import java.net.URI;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class QNameTest {
+ private final String namespace = "urn:foo", revision = "2013-12-24", localName = "bar";
+ private final URI ns;
+
+ public QNameTest() throws Exception {
+ this.ns = new URI(namespace);
+ }
+
+ @Test
+ public void testStringSerialization() throws Exception {
+ {
+ QName qName = QName.create(namespace, revision, localName);
+ assertEquals(QName.QNAME_LEFT_PARENTHESIS + namespace + QName.QNAME_REVISION_DELIMITER
+ + revision + QName.QNAME_RIGHT_PARENTHESIS + localName, qName.toString());
+ QName copied = QName.create(qName.toString());
+ assertEquals(qName, copied);
+ }
+ // no revision
+ {
+ QName qName = new QName(ns, localName);
+ assertEquals(QName.QNAME_LEFT_PARENTHESIS + namespace + QName.QNAME_RIGHT_PARENTHESIS
+ + localName, qName.toString());
+ QName copied = QName.create(qName.toString());
+ assertEquals(qName, copied);
+ }
+ // no namespace nor revision
+ {
+ QName qName = new QName((URI) null, localName);
+ assertEquals(localName, qName.toString());
+ QName copied = QName.create(qName.toString());
+ assertEquals(qName, copied);
+ }
+ }
+
+ @Test
+ public void testIllegalLocalNames() {
+ assertLocalNameFails(null);
+ assertLocalNameFails("");
+ assertLocalNameFails("(");
+ assertLocalNameFails(")");
+ assertLocalNameFails("?");
+ assertLocalNameFails("&");
+ }
+
+ private void assertLocalNameFails(String localName) {
+ try {
+ new QName((URI)null, localName);
+ fail("Local name should fail:" + localName);
+ } catch (IllegalArgumentException e) {
+
+ }
+ }
+
+}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Strings;
+
public final class YangParserListenerImpl extends YangParserBaseListener {
private static final Logger LOGGER = LoggerFactory.getLogger(YangParserListenerImpl.class);
private static final String AUGMENT_STR = "augment";
nodeType = new QName(namespace, revision, splittedElement[0], splittedElement[1]);
}
- QName qname;
- if (nodeParameter != null) {
+ QName qname = null;
+ if (!Strings.isNullOrEmpty(nodeParameter)) {
String[] splittedName = nodeParameter.split(":");
if (splittedName.length == 2) {
qname = new QName(null, null, splittedName[0], splittedName[1]);
qname = new QName(namespace, revision, yangModelPrefix, splittedName[0]);
}
} else {
- qname = new QName(namespace, revision, yangModelPrefix, nodeParameter);
+ qname = nodeType;
}
-
- addNodeToPath(new QName(namespace, revision, yangModelPrefix, nodeParameter));
+ addNodeToPath(qname);
SchemaPath path = createActualSchemaPath(actualPath.peek());
UnknownSchemaNodeBuilder builder = moduleBuilder.addUnknownSchemaNode(line, qname, path);