private def GeneratedTypeBuilder addDefaultInterfaceDefinition(String packageName, SchemaNode schemaNode,
Type parent) {
val it = addRawInterfaceDefinition(packageName, schemaNode, "");
- qnameConstant(BindingMapping.QNAME_STATIC_FIELD_NAME,schemaNode.QName);
if (parent === null) {
addImplementsType(DATA_OBJECT);
} else {
//FIXME: Validation of name conflict
val newType = new GeneratedTypeBuilderImpl(packageName, genTypeName);
+ qnameConstant(newType,BindingMapping.QNAME_STATIC_FIELD_NAME,schemaNode.QName);
newType.addComment(schemaNode.getDescription());
if (!genTypeBuilders.containsKey(packageName)) {
val Map<String, GeneratedTypeBuilder> builders = new HashMap();
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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
+-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
<artifactId>checkstyle</artifactId>
- <version>5.6</version>
+ <version>5.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
return identifier.getText();
}
- public static boolean itsAFieldVariable(final DetailAST aAST) {
+ public static boolean isAFieldVariable(final DetailAST aAST) {
return aAST.getParent().getType() == TokenTypes.OBJBLOCK;
}
return LOG_METHODS.contains(methodName);
}
+ public static String getClassName(final DetailAST aAST) {
+ DetailAST parent = aAST.getParent();
+ while(parent.getType() != TokenTypes.CLASS_DEF && parent.getType() != TokenTypes.ENUM_DEF) {
+ parent = parent.getParent();
+ }
+ return parent.findFirstToken(TokenTypes.IDENT).getText();
+ }
+
}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.checkstyle;
+
+import static org.opendaylight.yangtools.checkstyle.CheckLoggingUtil.isAFieldVariable;
+
+import com.puppycrawl.tools.checkstyle.api.Check;
+import com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.api.TokenTypes;
+
+public class LoggerDeclarationsCountCheck extends Check {
+
+ private static final String LOG_MESSAGE = "Logger might be declared only once.";
+ private String prevClassName = "";
+
+ @Override
+ public int[] getDefaultTokens() {
+ return new int[]{TokenTypes.VARIABLE_DEF};
+ }
+
+ @Override
+ public void visitToken(DetailAST aAST) {
+ if (CheckLoggingUtil.isLoggerType(aAST) && isAFieldVariable(aAST)) {
+ final String className = CheckLoggingUtil.getClassName(aAST);
+ if(this.prevClassName.equals(className)) {
+ log(aAST.getLineNo(), LOG_MESSAGE);
+ }
+ this.prevClassName = className;
+ }
+ }
+
+ @Override
+ public void finishTree(DetailAST aRootAST) {
+ super.finishTree(aRootAST);
+ this.prevClassName = "";
+ }
+
+}
public void visitToken(DetailAST aAST) {
final String methodName = CheckLoggingUtil.getMethodName(aAST);
if(methodName.equals(METHOD_NAME)) {
- final String className = getClassName(aAST);
+ final String className = CheckLoggingUtil.getClassName(aAST);
final String parameter = aAST.findFirstToken(TokenTypes.ELIST).getFirstChild().getFirstChild().getFirstChild().getText();
if(!parameter.equals(className)) {
log(aAST.getLineNo(), LOG_MESSAGE);
}
}
- private String getClassName(final DetailAST aAST) {
- DetailAST parent = aAST.getParent();
- while(parent.getType() != TokenTypes.CLASS_DEF && parent.getType() != TokenTypes.ENUM_DEF) {
- parent = parent.getParent();
- }
- return parent.findFirstToken(TokenTypes.IDENT).getText();
- }
-
}
public void visitToken(DetailAST aAST) {
if(aAST.getType() == TokenTypes.VARIABLE_DEF) {
final String typeName = CheckLoggingUtil.getTypeName(aAST);
- if (CheckLoggingUtil.itsAFieldVariable(aAST) && typeName.contains("." + LOGGER_TYPE_NAME)) {
+ if (CheckLoggingUtil.isAFieldVariable(aAST) && typeName.contains("." + LOGGER_TYPE_NAME)) {
if(!typeName.equals(LOGGER_TYPE_FULL_NAME)) {
log(aAST.getLineNo(), LOG_MESSAGE);
}
@Override
public void visitToken(DetailAST aAST) {
- if (CheckLoggingUtil.itsAFieldVariable(aAST) && CheckLoggingUtil.isLoggerType(aAST) && !hasPrivatStaticFinalModifier(aAST)) {
+ if (CheckLoggingUtil.isAFieldVariable(aAST) && CheckLoggingUtil.isLoggerType(aAST) && !hasPrivatStaticFinalModifier(aAST)) {
log(aAST.getLineNo(), LOG_MESSAGE);
}
}
@Override
public void visitToken(DetailAST aAST) {
final String variableName = CheckLoggingUtil.getVariableName(aAST);
- if (CheckLoggingUtil.itsAFieldVariable(aAST) && CheckLoggingUtil.isLoggerType(aAST) && !variableName.equals(LOGGER_VAR_NAME)) {
+ if (CheckLoggingUtil.isAFieldVariable(aAST) && CheckLoggingUtil.isLoggerType(aAST) && !variableName.equals(LOGGER_VAR_NAME)) {
log(aAST.getLineNo(), LOG_MESSAGE);
}
}
<module name="org.opendaylight.yangtools.checkstyle.LogMessagePlaceholderCountCheck" />
</module>
+ <module name="TreeWalker">
+ <module name="org.opendaylight.yangtools.checkstyle.LoggerDeclarationsCountCheck"/>
+ </module>
+
+ <module name="FileTabCharacter">
+ <property name="eachLine" value="true"/>
+ </module>
+
<module name="RegexpSingleline">
- <property name="format" value="(\.|\b)Logger "/>
- <property name="message" value="Logger might be declared only once."/>
- <property name="minimum" value="0"/>
- <property name="maximum" value="1"/>
+ <property name="format" value="\s+$"/>
+ <property name="message" value="Line has trailing spaces."/>
+ </module>
+
+ <module name="RegexpMultiline">
+ <property name="format" value="(\r\n|\r)"/>
+ <property name="message" value="Line has Windows line delimiter."/>
+ </module>
+
+ <module name="TreeWalker">
+ <module name="Indentation">
+ <property name="caseIndent" value="0"/>
+ <property name="throwsIndent" value="8"/>
+ </module>
+
+ <module name="UnusedImports"/>
+
+ <module name="ImportOrder">
+ <property name="ordered" value="true"/>
+ <property name="separated" value="true"/>
+ <property name="option" value="above"/>
+ </module>
</module>
</module>
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.yangtools.checkstyle;\r
+\r
+import java.util.Comparator;\r
+import java.util.Map;\r
+\r
+import static java.lang.String.CASE_INSENSITIVE_ORDER;\r
+\r
+import com.google.common.collect.Maps;\r
+import com.google.common.collect.Lists;\r
+\r
+public class CheckCodingStyleTestClass {\r
+\r
+ public CheckCodingStyleTestClass() {\r
+ Comparator<String> string = CASE_INSENSITIVE_ORDER; \r
+ \r
+ Map<String, String> map = Maps.newHashMap();\r
+ }\r
+}\r
LOG.warn("foo {}", string);
LOG.warn("foo {}", string, e);
}
-}
\ No newline at end of file
+}
@Test
public void testLoggerChecks() throws Exception {
verify(CheckLoggingTestClass.class, "15: Logger must be declared as private static final.", "15: Logger name should be LOG.",
- "16: Logger might be declared only once.", "16: Logger must be slf4j.", "22: Line contains printStacktrace",
+ "17: Logger might be declared only once.", "16: Logger must be slf4j.", "22: Line contains printStacktrace",
"23: Line contains console output", "24: Line contains console output",
"15: LoggerFactory.getLogger Class argument is incorrect.", "20: Log message contains string concatenation.",
"26: Log message placeholders count is incorrect.", "32: Log message placeholders count is incorrect");
}
+ @Test
+ public void testCodingChecks() {
+ verify(CheckCodingStyleTestClass.class, "9: Line has Windows line delimiter.", "14: Wrong order for", "24:1: Line contains a tab character.",
+ "22: Line has trailing spaces.", "22: ctor def child at indentation level 16 not at correct indentation, 8", "17:8: Unused import",
+ "23: Line has trailing spaces.");
+ }
+
private void verify(final Class<?> testClass, final String... expectedMessages) {
final String filePath = System.getProperty("user.dir") + File.separator + "src" + File.separator + "test" + File.separator + "java" + File.separator + testClass.getName().replaceAll("\\.", "/") + ".java";
final File testFile = new File(filePath);
*/
package org.opendaylight.yangtools.concepts;
-import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
/**
* Utility registration handle. It is a convenience for register-style method
* installed.
*/
public abstract class AbstractRegistration implements AutoCloseable {
- private AtomicBoolean closed = new AtomicBoolean();
-
+ private static final AtomicIntegerFieldUpdater<AbstractRegistration> CLOSED_UPDATER =
+ AtomicIntegerFieldUpdater.newUpdater(AbstractRegistration.class, "closed");
+ private volatile int closed = 0;
+
/**
* Remove the state referenced by this registration. This method is
* guaranteed to be called at most once. The referenced state must be
*/
protected abstract void removeRegistration();
+ /**
+ * Query the state of this registration. Returns true if it was
+ * closed.
+ *
+ * @return true if the registration was closed, false otherwise.
+ */
+ protected final boolean isClosed() {
+ return CLOSED_UPDATER.get(this) != 0;
+ }
+
@Override
public final void close() {
- if (closed.compareAndSet(false, true)) {
+ if (CLOSED_UPDATER.compareAndSet(this, 0, 1)) {
removeRegistration();
}
}
/**
* Unregister the listener. No events should be delivered to the listener
* once this method returns successfully. While the interface contract
- * allows an implementation to ignore the occurence of RuntimeExceptions,
+ * allows an implementation to ignore the occurrence of RuntimeExceptions,
* implementations are strongly encouraged to deal with such exceptions
* internally and to ensure invocations of this method do not fail in such
* circumstances.
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
- <Export-Package>org.opendaylight.yangtools.util</Export-Package>
- <Embed-Dependency>java-concurrent-hash-trie-map;inline=true</Embed-Dependency>
+ <instructions>
+ <Export-Package>org.opendaylight.yangtools.util</Export-Package>
+ <Embed-Dependency>java-concurrent-hash-trie-map;inline=true</Embed-Dependency>
+ </instructions>
</configuration>
</plugin>
</plugins>
--- /dev/null
+/*
+ * Copyright (c) 2014 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.util;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.ForwardingBlockingQueue;
+
+/**
+ * Utility methods for dealing with {@link ExecutorService}s.
+ */
+public final class ExecutorServiceUtil {
+ private static final class WaitInQueueExecutionHandler implements RejectedExecutionHandler {
+ @Override
+ public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) {
+ try {
+ executor.getQueue().put(r);
+ } catch (InterruptedException e) {
+ LOG.debug("Intterupted while waiting for queue", e);
+ throw new RejectedExecutionException("Interrupted while waiting for queue", e);
+ }
+ }
+ }
+
+ private static final Logger LOG = LoggerFactory.getLogger(ExecutorServiceUtil.class);
+ private static final RejectedExecutionHandler WAIT_IN_QUEUE_HANDLER = new WaitInQueueExecutionHandler();
+
+ private ExecutorServiceUtil() {
+ throw new UnsupportedOperationException("Utility class");
+ }
+
+ /**
+ * Create a {@link BlockingQueue} which does not allow for non-blocking addition to the queue.
+ * This is useful with {@link #waitInQueueExecutionHandler()} to turn force a
+ * {@link ThreadPoolExecutor} to create as many threads as it is configured to before starting
+ * to fill the queue.
+ *
+ * @param delegate Backing blocking queue.
+ * @return A new blocking queue backed by the delegate
+ */
+ public <E> BlockingQueue<E> offerFailingBlockingQueue(final BlockingQueue<E> delegate) {
+ return new ForwardingBlockingQueue<E>() {
+ @Override
+ public boolean offer(final E o) {
+ return false;
+ }
+
+ @Override
+ protected BlockingQueue<E> delegate() {
+ return delegate;
+ }
+ };
+ }
+
+ /**
+ * Return a {@link RejectedExecutionHandler} which blocks on the {@link ThreadPoolExecutor}'s
+ * backing queue if a new thread cannot be spawned.
+ *
+ * @return A shared RejectedExecutionHandler instance.
+ */
+ public RejectedExecutionHandler waitInQueueExecutionHandler() {
+ return WAIT_IN_QUEUE_HANDLER;
+ }
+}
namespace "urn:ietf:params:xml:ns:yang:ietf-restconf";
prefix "restconf";
- import ietf-yang-types { prefix yang; }
+ import ietf-yang-types { prefix yang; revision-date 2013-07-15; }
import ietf-inet-types { prefix inet; }
organization
@Override
public Optional<QName> load(final Class<?> key) throws Exception {
+ return resolveQNameNoCache(key);
+ }
+ }
+
+ /**
+ *
+ * Tries to resolve QName for supplied class.
+ *
+ * Looks up for static field with name from constant {@link BindingMapping#QNAME_STATIC_FIELD_NAME}
+ * and returns value if present.
+ *
+ * If field is not present uses {@link #computeQName(Class)} to compute QName for missing types.
+ *
+ * @param key
+ * @return
+ */
+ private static Optional<QName> resolveQNameNoCache(final Class<?> key) {
+ try {
+ Field field = key.getField(BindingMapping.QNAME_STATIC_FIELD_NAME);
+ Object obj = field.get(null);
+ if (obj instanceof QName) {
+ return Optional.of((QName) obj);
+ }
+
+ } catch (NoSuchFieldException e) {
+ return Optional.of(computeQName(key));
+
+ } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
+ /*
+ *
+ * It is safe to log this this exception on debug, since
+ * this method should not fail. Only failures are possible if
+ * the runtime / backing.
+ *
+ */
+ LOG.debug("Unexpected exception during extracting QName for {}",key,e);
+ }
+ return Optional.absent();
+ }
+
+ /**
+ * Computes QName for supplied class
+ *
+ * Namespace and revision are same as {@link YangModuleInfo}
+ * associated with supplied class.
+ * <p>
+ * If class is
+ * <ul>
+ * <li>rpc input: local name is "input".
+ * <li>rpc output: local name is "output".
+ * <li>augmentation: local name is "module name".
+ * </ul>
+ *
+ * There is also fallback, if it is not possible to compute QName
+ * using following algorithm returns module QName.
+ *
+ * FIXME: Extend this algorithm to also provide QName for YANG modeled simple types.
+ *
+ * @throws IllegalStateException If YangModuleInfo could not be resolved
+ * @throws IllegalArgumentException If supplied class was not derived from YANG model.
+ *
+ */
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private static QName computeQName(final Class key) {
+ if(isBindingClass(key)) {
+ YangModuleInfo moduleInfo;
try {
- Field field = key.getField(BindingMapping.QNAME_STATIC_FIELD_NAME);
- Object obj = field.get(null);
- if (obj instanceof QName) {
- return Optional.of((QName) obj);
- }
- } catch (NoSuchFieldException e) {
- if (Augmentation.class.isAssignableFrom(key)) {
- YangModuleInfo moduleInfo = getModuleInfo(key);
- return Optional.of(QName.create(moduleInfo.getNamespace(), moduleInfo.getRevision(),
- moduleInfo.getName()));
+ moduleInfo = getModuleInfo(key);
+ } catch (Exception e) {
+ throw new IllegalStateException("Unable to get QName for " + key + ". YangModuleInfo was not found.",e);
+ }
+ final QName module = getModuleQName(moduleInfo);
+ if (Augmentation.class.isAssignableFrom(key)) {
+ return module;
+ } else if(isRpcType(key)) {
+ final String className = key.getSimpleName();
+ if(className.endsWith(BindingMapping.RPC_OUTPUT_SUFFIX)) {
+ return QName.create(module,"output");
+ } else {
+ return QName.create(module,"input");
}
- } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
- /*
- *
- * It is safe to log this this exception on debug, since
- * this method should not fail. Only failures are possible if
- * the runtime / backing.
- *
- */
- LOG.debug("Unexpected exception during extracting QName for {}",key,e);
}
- return Optional.absent();
+ /*
+ * Fallback for Binding types which fo not have QNAME
+ * field
+ */
+ return module;
+ } else {
+ throw new IllegalArgumentException("Supplied class "+key+"is not derived from YANG.");
}
}
+
+ public static QName getModuleQName(final YangModuleInfo moduleInfo) {
+ checkArgument(moduleInfo != null, "moduleInfo must not be null.");
+ return QName.create(moduleInfo.getNamespace(), moduleInfo.getRevision(),
+ moduleInfo.getName());
+ }
+
+
}
* same local name, but from different schemas.
*
* <ul>
- * <li><b>XMLNamespace</b> - the namespace assigned to the YANG module which
+ * <li><b>XMLNamespace</b> - {@link #getNamespace()} - the namespace assigned to the YANG module which
* defined element, type, procedure or notification.</li>
- * <li><b>Revision</b> - the revision of the YANG module which describes the
+ * <li><b>Revision</b> - {@link #getRevision()} - the revision of the YANG module which describes the
* element</li>
- * <li><b>LocalName</b> - the YANG schema identifier which were defined for this
+ * <li><b>LocalName</b> - {@link #getLocalName()} - the YANG schema identifier which were defined for this
* node in the YANG module</li>
* </ul>
*
+ * QName may also have <code>prefix</code> assigned, but prefix does not
+ * affect equality and identity of two QNames and carry only information
+ * which may be useful for serializers / deserializers.
+ *
*
*/
public final class QName implements Immutable, Serializable, Comparable<QName> {
static final String QNAME_LEFT_PARENTHESIS = "(";
static final String QNAME_RIGHT_PARENTHESIS = ")";
- private static final Pattern QNAME_PATTERN_FULL = Pattern.compile(
- "^\\((.+)\\" + QNAME_REVISION_DELIMITER + "(.+)\\)(.+)$");
- private static final Pattern QNAME_PATTERN_NO_REVISION = Pattern.compile(
- "^\\((.+)\\)(.+)$");
- private static final Pattern QNAME_PATTERN_NO_NAMESPACE_NO_REVISION = Pattern.compile(
- "^(.+)$");
+ private static final Pattern QNAME_PATTERN_FULL = Pattern.compile("^\\((.+)\\" + QNAME_REVISION_DELIMITER
+ + "(.+)\\)(.+)$");
+ private static final Pattern QNAME_PATTERN_NO_REVISION = Pattern.compile("^\\((.+)\\)(.+)$");
+ private static final Pattern QNAME_PATTERN_NO_NAMESPACE_NO_REVISION = Pattern.compile("^(.+)$");
- private static final char[] ILLEGAL_CHARACTERS = new char[] {'?', '(', ')', '&'};
+ private static final char[] ILLEGAL_CHARACTERS = new char[] { '?', '(', ')', '&' };
- //Mandatory
+ // Mandatory
private final QNameModule module;
- //Mandatory
+ // Mandatory
private final String localName;
- //Nullable
+ // Nullable
private final String prefix;
+ private QName(final QNameModule module, final String prefix, final String localName) {
+ this.localName = checkLocalName(localName);
+ this.prefix = prefix;
+ this.module = module;
+ }
+
/**
* QName Constructor.
*
* locally defined prefix assigned to local name
* @param localName
* YANG schema identifier
+ *
*/
public QName(final URI namespace, final Date revision, final String prefix, final String localName) {
- this.localName = checkLocalName(localName);
- this.prefix = prefix;
- this.module = QNameModule.create(namespace, revision);
+ this(QNameModule.create(namespace, revision), prefix, localName);
}
/**
throw new IllegalArgumentException("Parameter 'localName' must be a non-empty string.");
}
- for (char c: ILLEGAL_CHARACTERS) {
+ for (char c : ILLEGAL_CHARACTERS) {
if (localName.indexOf(c) != -1) {
throw new IllegalArgumentException(String.format(
- "Parameter 'localName':'%s' contains illegal character '%s'",
- localName, c));
+ "Parameter 'localName':'%s' contains illegal character '%s'", localName, c));
}
}
return localName;
* the revision of the YANG module
* @param localName
* YANG schema identifier
+ *
+ * @deprecated Use {@link #create(URI, Date, String)} instead.
*/
+ @Deprecated
public QName(final URI namespace, final Date revision, final String localName) {
- this(namespace, revision, null, localName);
+ this(QNameModule.create(namespace, revision), null, localName);
}
+ /**
+ * Construct new QName which reuses namespace, revision and prefix from
+ * base.
+ *
+ * @param base
+ * @param localName
+ * @deprecated Use {@link #create(QName, String)} instead.
+ */
+ @Deprecated
public QName(final QName base, final String localName) {
this(base.getNamespace(), base.getRevision(), base.getPrefix(), localName);
}
/**
- * @deprecated Use {@link #create(String)} instead.
- * This implementation is broken.
+ * @deprecated Use {@link #create(String)} instead. This implementation is
+ * broken.
*/
@Deprecated
public QName(final String input) throws ParseException {
matcher = QNAME_PATTERN_NO_NAMESPACE_NO_REVISION.matcher(input);
if (matcher.matches()) {
String localName = matcher.group(1);
- return new QName((URI)null, localName);
+ return new QName((URI) null, localName);
}
throw new IllegalArgumentException("Invalid input:" + input);
}
return result;
}
+ /**
+ *
+ * Compares the specified object with this list for equality. Returns
+ * <tt>true</tt> if and only if the specified object is also instance of
+ * {@link QName} and its {@link #getLocalName()}, {@link #getNamespace()} and
+ * {@link #getRevision()} are equals to same properties of this instance.
+ *
+ * @param o the object to be compared for equality with this QName
+ * @return <tt>true</tt> if the specified object is equal to this QName
+ *
+ */
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
- public static QName create(final QName base, final String localName){
+ public static QName create(final QName base, final String localName) {
return new QName(base, localName);
}
- public static QName create(final URI namespace, final Date revision, final String localName){
- return new QName(namespace, revision, localName);
+ /**
+ *
+ * Creates new QName.
+ *
+ * @param namespace Namespace of QName or null if namespace is undefined.
+ * @param revision Revision of namespace or null if revision is unspecified.
+ * @param localName Local name part of QName. MUST NOT BE null.
+ * @return Instance of QName
+ */
+ public static QName create(final URI namespace, final Date revision, final String localName) {
+ return new QName(QNameModule.create(namespace, revision), null,localName);
}
-
- public static QName create(final String namespace, final String revision, final String localName) throws IllegalArgumentException{
+ /**
+ *
+ * Creates new QName.
+ *
+ * @param namespace
+ * Namespace of QName, MUST NOT BE Null.
+ * @param revision
+ * Revision of namespace / YANG module. MUST NOT BE null, MUST BE
+ * in format <code>YYYY-mm-dd</code>.
+ * @param localName
+ * Local name part of QName. MUST NOT BE null.
+ * @return
+ * @throws NullPointerException
+ * If any of paramaters is null.
+ * @throws IllegalArgumentException
+ * If <code>namespace</code> is not valid URI or
+ * <code>revision</code> is not according to format
+ * <code>YYYY-mm-dd</code>.
+ */
+ public static QName create(final String namespace, final String revision, final String localName)
+ throws IllegalArgumentException {
final URI namespaceUri;
try {
namespaceUri = new URI(namespace);
- } catch (URISyntaxException ue) {
+ } catch (URISyntaxException ue) {
throw new IllegalArgumentException(String.format("Namespace '%s' is not a valid URI", namespace), ue);
}
return sb.toString();
}
+ /**
+ * Return string representation of revision in format
+ * <code>YYYY-mm-dd</code>
+ *
+ * YANG Specification defines format for <code>revision</code> as
+ * YYYY-mm-dd. This format for revision is reused accross multiple places
+ * such as capabilities URI, YANG modules, etc.
+ *
+ * @return String representation of revision or null, if revision is not
+ * set.
+ */
public String getFormattedRevision() {
return module.getFormattedRevision();
}
+ /**
+ * Creates copy of this with revision and prefix unset.
+ *
+ * @return copy of this QName with revision and prefix unset.
+ */
public QName withoutRevision() {
return QName.create(getNamespace(), null, localName);
}
public static Date parseRevision(final String formatedDate) {
try {
return getRevisionFormat().parse(formatedDate);
- } catch (ParseException| RuntimeException e) {
- throw new IllegalArgumentException(String.format("Revision '%s'is not in a supported format", formatedDate), e);
+ } catch (ParseException | RuntimeException e) {
+ throw new IllegalArgumentException(
+ String.format("Revision '%s'is not in a supported format", formatedDate), e);
}
}
+ /**
+ * Formats {@link Date} representing revision to format
+ * <code>YYYY-mm-dd</code>
+ *
+ * YANG Specification defines format for <code>revision</code> as
+ * YYYY-mm-dd. This format for revision is reused accross multiple places
+ * such as capabilities URI, YANG modules, etc.
+ *
+ * @param revision
+ * Date object to format or null
+ * @return String representation or null if the input was null.
+ */
public static String formattedRevision(final Date revision) {
- if(revision == null) {
+ if (revision == null) {
return null;
}
return getRevisionFormat().format(revision);
}
+ /**
+ *
+ * Compares this QName to other, without comparing revision.
+ *
+ * Compares instance of this to other instance of QName and returns true if
+ * both instances have equal <code>localName</code> ({@link #getLocalName()}
+ * ) and <code>namespace</code> ({@link #getNamespace()}).
+ *
+ * @param other
+ * Other QName. Must not be null.
+ * @return true if this instance and other have equals localName and
+ * namespace.
+ * @throws NullPointerException
+ * if <code>other</code> is null.
+ */
public boolean isEqualWithoutRevision(final QName other) {
return localName.equals(other.getLocalName()) && Objects.equals(getNamespace(), other.getNamespace());
}
*/
package org.opendaylight.yangtools.yang.common;
+/**
+ *
+ * Representation of Error in YANG enabled system.
+ *
+ * Which may be send / received by YANG modeled / enabled systems.
+ *
+ */
public interface RpcError {
+
+ /**
+ *
+ * Returns error severity, as determined by component reporting the error.
+ *
+ * @return error severity
+ */
ErrorSeverity getSeverity();
+ /**
+ *
+ * Returns a string identifying the error condition.
+ *
+ * @return string identifying the error condition.
+ */
String getTag();
+ /**
+ *
+ * Returns a string identifying the data-model-specific or
+ * implementation-specific error condition, if one exists. This element will
+ * not be present if no appropriate application error-tag can be associated
+ * with a particular error condition. If a data-model-specific and an
+ * implementation-specific error-app-tag both exist, then the
+ * data-model-specific value MUST be used by the reporter.
+ *
+ * @return Returns a string identifying the data-model-specific or
+ * implementation-specific error condition, or null if does not
+ * exists.
+ */
String getApplicationTag();
+ /**
+ *
+ * Returns a string suitable for human display that describes the error
+ * condition. This element will not be present if no appropriate message is
+ * provided for a particular error condition.
+ *
+ * @return returns an error description for human display.
+ */
String getMessage();
+ /**
+ *
+ * Contains protocol- or data-model-specific error content. This value may
+ * be not be present if no such error content is provided for a particular
+ * error condition.
+ *
+ * The list in Appendix A defines any mandatory error-info content for each
+ * error. After any protocol-mandated content, a data model definition MAY
+ * mandate that certain application-layer error information be included in
+ * the error-info container.
+ *
+ * An implementation MAY include additional information to provide extended
+ * and/or implementation- specific debugging information.
+ *
+ * @return
+ */
String getInfo();
-
+
+ /**
+ *
+ * Return a cause if available.
+ *
+ * @return cause of this error, if error was triggered by exception.
+ */
Throwable getCause();
-
+
+ /**
+ * Returns the conceptual layer that on which the error occurred.
+ *
+ * @return the conceptual layer that on which the error occurred.
+ */
ErrorType getErrorType();
public enum ErrorSeverity {
import java.util.Collection;
+/**
+ *
+ * Result of call to YANG enabled system.
+ *
+ *
+ * @param <T> Return type
+ */
public interface RpcResult<T> {
+
+ /**
+ * True if processing of request was successful
+ *
+ * @return true if processing was successful.
+ */
boolean isSuccessful();
+ /**
+ *
+ * Returns result of call or null if no result is available.
+ *
+ * @return result of call or null if no result is available.
+ *
+ */
T getResult();
+ /**
+ *
+ * Returns set of errors and warnings which occured during processing
+ * the request.
+ *
+ * @return
+ */
Collection<RpcError> getErrors();
}
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-model-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
package org.opendaylight.yangtools.yang.data.api;
import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
import java.util.Set;
import org.opendaylight.yangtools.concepts.Builder;
}
}
+ static int hashCode( Object value ) {
+ if( value == null ) {
+ return 0;
+ }
+
+ if( value.getClass().equals( byte[].class ) ) {
+ return Arrays.hashCode( (byte[])value );
+ }
+
+ if( value.getClass().isArray() ) {
+ int hash = 0;
+ int length = Array.getLength( value );
+ for( int i = 0; i < length; i++ ) {
+ hash += Objects.hashCode( Array.get( value, i ) );
+ }
+
+ return hash;
+ }
+
+ return Objects.hashCode( value );
+ }
+
// Static factories & helpers
public static InstanceIdentifier of(final QName name) {
}
public NodeIdentifierWithPredicates(final QName node, final QName key, final Object value) {
- this.nodeType = node;
- this.keyValues = ImmutableMap.of(key, value);
+ this( node, ImmutableMap.of(key, value) );
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + ((keyValues == null) ? 0 : keyValues.hashCode());
+ result = prime * result + ((keyValues == null) ? 0 : hashKeyValues());
result = prime * result + ((nodeType == null) ? 0 : nodeType.hashCode());
return result;
}
+ private int hashKeyValues() {
+ int hash = 0;
+ for( Entry<QName,Object> entry: keyValues.entrySet() ) {
+ hash += Objects.hashCode( entry.getKey() ) + InstanceIdentifier.hashCode( entry.getValue() );
+ }
+
+ return hash;
+ }
+
@Override
public boolean equals(final Object obj) {
if (this == obj) {
if (other.keyValues != null) {
return false;
}
- } else if (!keyValues.equals(other.keyValues)) {
+ } else if (!keyValuesEquals(other.keyValues)) {
return false;
}
if (nodeType == null) {
return true;
}
+ private boolean keyValuesEquals( Map<QName, Object> otherKeyValues ) {
+ if( otherKeyValues == null || keyValues.size() != otherKeyValues.size() ) {
+ return false;
+ }
+
+ boolean result = true;
+ for( Entry<QName,Object> entry: keyValues.entrySet() ) {
+ if( !otherKeyValues.containsKey( entry.getKey() ) ||
+ !Objects.deepEquals( entry.getValue(), otherKeyValues.get( entry.getKey() ) ) ) {
+
+ result = false;
+ break;
+ }
+ }
+
+ return result;
+ }
+
@Override
public String toString() {
return nodeType + "[" + keyValues + "]";
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + ((value == null) ? 0 : value.hashCode());
+ result = prime * result + ((value == null) ? 0 : InstanceIdentifier.hashCode( value ) );
result = prime * result + ((nodeType == null) ? 0 : nodeType.hashCode());
return result;
}
return false;
}
NodeWithValue other = (NodeWithValue) obj;
- if (value == null) {
- if (other.value != null) {
- return false;
- }
- } else if (!value.equals(other.value)) {
- return false;
- }
- if (nodeType == null) {
- if (other.nodeType != null) {
- return false;
- }
- } else if (!nodeType.equals(other.nodeType)) {
- return false;
- }
- return true;
+ return Objects.deepEquals(value, other.value) && Objects.equals(nodeType, other.nodeType);
}
@Override
--- /dev/null
+/*
+ * Copyright (c) 2014 Brocade Communications 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.data.api;
+
+import static org.junit.Assert.*;
+import static org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
+
+import java.util.Collections;
+import java.util.Map.Entry;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+/**
+ * Unit tests for InstanceIdentifier.
+ *
+ * @author Thomas Pantelis
+ */
+public class InstanceIdentifierTest {
+
+ static QName nodeName1 = QName.create("test", "2014-5-28", "node1");
+ static QName nodeName2 = QName.create("test", "2014-5-28", "node2");
+ static QName nodeName3 = QName.create("test", "2014-5-28", "node3");
+ static QName nodeName4 = QName.create("test", "2014-5-28", "node4");
+ static QName key1 = QName.create("test", "2014-5-28", "key1");
+ static QName key2 = QName.create("test", "2014-5-28", "key2");
+ static QName key3 = QName.create("test", "2014-5-28", "key3");
+
+ @Test
+ public void testHashCodeEquals() {
+
+ InstanceIdentifier id1 = new InstanceIdentifier(
+ Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2)));
+ InstanceIdentifier id2 = new InstanceIdentifier(
+ Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2)));
+ InstanceIdentifier id3 = new InstanceIdentifier(
+ Lists.newArrayList(new NodeIdentifier(nodeName2), new NodeIdentifier(nodeName1)));
+ InstanceIdentifier id4 = new InstanceIdentifier(
+ Lists.newArrayList(new NodeIdentifier(nodeName1)));
+
+ assertEquals( "hashCode", id1.hashCode(), id2.hashCode() );
+ assertEquals( "equals", true, id1.equals( id2 ) );
+
+ assertEquals( "equals", false, id1.equals( id3 ) );
+ assertEquals( "equals", false, id1.equals( id4 ) );
+ assertEquals( "equals", false, id1.equals( new Object() ) );
+ }
+
+ @Test
+ public void testNode() {
+
+ InstanceIdentifier id = new InstanceIdentifier(
+ Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2)));
+
+ InstanceIdentifier newID = id.node( nodeName3 );
+
+ assertNotNull( "InstanceIdentifier is null", newID );
+ assertEquals( "Path size", 3, newID.getPath().size() );
+ assertEquals( "PathArg 1 node type", nodeName1, newID.getPath().get(0).getNodeType() );
+ assertEquals( "PathArg 2 node type", nodeName2, newID.getPath().get(1).getNodeType() );
+ assertEquals( "PathArg 3 node type", nodeName3, newID.getPath().get(2).getNodeType() );
+
+ newID = id.node( new NodeIdentifier( nodeName3 ) );
+
+ assertNotNull( "InstanceIdentifier is null", newID );
+ assertEquals( "Path size", 3, newID.getPath().size() );
+ assertEquals( "PathArg 1 node type", nodeName1, newID.getPath().get(0).getNodeType() );
+ assertEquals( "PathArg 2 node type", nodeName2, newID.getPath().get(1).getNodeType() );
+ assertEquals( "PathArg 3 node type", nodeName3, newID.getPath().get(2).getNodeType() );
+ }
+
+ @Test
+ public void testRelativeTo() {
+
+ InstanceIdentifier id1 = new InstanceIdentifier(
+ Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2),
+ new NodeIdentifier(nodeName3), new NodeIdentifier(nodeName4)));
+ InstanceIdentifier id2 = new InstanceIdentifier(
+ Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2)));
+ InstanceIdentifier id3 = new InstanceIdentifier(
+ Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2)));
+
+ Optional<InstanceIdentifier> relative = id1.relativeTo( id2 );
+
+ assertEquals( "isPresent", true, relative.isPresent() );
+ assertEquals( "Path size", 2, relative.get().getPath().size() );
+ assertEquals( "PathArg 1 node type", nodeName3, relative.get().getPath().get(0).getNodeType() );
+ assertEquals( "PathArg 2 node type", nodeName4, relative.get().getPath().get(1).getNodeType() );
+
+ relative = id2.relativeTo( id3 );
+ assertEquals( "isPresent", true, relative.isPresent() );
+ assertEquals( "Path size", 0, relative.get().getPath().size() );
+
+ relative = id2.relativeTo( id1 );
+ assertEquals( "isPresent", false, relative.isPresent() );
+ }
+
+ @Test
+ public void testContains() {
+
+ InstanceIdentifier id1 = new InstanceIdentifier(
+ Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2),
+ new NodeIdentifier(nodeName3), new NodeIdentifier(nodeName4)));
+ InstanceIdentifier id2 = new InstanceIdentifier(
+ Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2)));
+ InstanceIdentifier id3 = new InstanceIdentifier(
+ Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2)));
+ InstanceIdentifier id4 = new InstanceIdentifier(
+ Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName3)));
+
+ assertEquals( "contains", true, id2.contains( id1 ) );
+ assertEquals( "contains", true, id2.contains( id3 ) );
+ assertEquals( "contains", false, id1.contains( id2 ) );
+ assertEquals( "contains", false, id2.contains( id4 ) );
+ }
+
+ @Test
+ public void testOf() {
+
+ InstanceIdentifier newID = InstanceIdentifier.of( nodeName1 );
+
+ assertNotNull( "InstanceIdentifier is null", newID );
+ assertEquals( "Path size", 1, newID.getPath().size() );
+ assertEquals( "PathArg 1 node type", nodeName1, newID.getPath().get(0).getNodeType() );
+
+ assertNotNull( newID.toString() ); // for code coverage
+ }
+
+ @Test
+ public void testBuilder() {
+
+ InstanceIdentifier newID = InstanceIdentifier.builder()
+ .node( nodeName1 )
+ .nodeWithKey( nodeName2, Collections.<QName,Object>singletonMap( key1, "foo" ) )
+ .nodeWithKey( nodeName3, key2, "bar" ).build();
+
+ assertNotNull( "InstanceIdentifier is null", newID );
+ assertEquals( "Path size", 3, newID.getPath().size() );
+ assertEquals( "PathArg 1 node type", nodeName1, newID.getPath().get(0).getNodeType() );
+ verifyNodeIdentifierWithPredicates( "PathArg 2", newID.getPath().get(1), nodeName2, key1, "foo" );
+ verifyNodeIdentifierWithPredicates( "PathArg 3", newID.getPath().get(2), nodeName3, key2, "bar" );
+
+ newID = InstanceIdentifier.builder( newID ).node( nodeName4 ).build();
+
+ assertNotNull( "InstanceIdentifier is null", newID );
+ assertEquals( "Path size", 4, newID.getPath().size() );
+ assertEquals( "PathArg 1 node type", nodeName1, newID.getPath().get(0).getNodeType() );
+ assertEquals( "PathArg 2 node type", nodeName2, newID.getPath().get(1).getNodeType() );
+ assertEquals( "PathArg 3 node type", nodeName3, newID.getPath().get(2).getNodeType() );
+ assertEquals( "PathArg 4 node type", nodeName4, newID.getPath().get(3).getNodeType() );
+
+ newID = InstanceIdentifier.builder( nodeName1 ).build();
+
+ assertNotNull( "InstanceIdentifier is null", newID );
+ assertEquals( "Path size", 1, newID.getPath().size() );
+ assertEquals( "PathArg 1 node type", nodeName1, newID.getPath().get(0).getNodeType() );
+ }
+
+ private void verifyNodeIdentifierWithPredicates(String prefix,
+ PathArgument arg, QName nodeName, QName key, Object value ) {
+
+ assertNotNull( prefix + " is null", arg );
+ assertEquals( prefix + " class", NodeIdentifierWithPredicates.class, arg.getClass() );
+ NodeIdentifierWithPredicates node = (NodeIdentifierWithPredicates)arg;
+ assertEquals( prefix + " node type", nodeName, node.getNodeType() );
+ assertEquals( prefix + " key values map size", 1, node.getKeyValues().size() );
+ Entry<QName, Object> entry = node.getKeyValues().entrySet().iterator().next();
+ assertEquals( prefix + " key values map entry key", key, entry.getKey() );
+ assertEquals( prefix + " key values map entry value", value, entry.getValue() );
+ }
+
+ @Test
+ public void testNodeIdentifierWithPredicates() {
+
+ NodeIdentifierWithPredicates node1 = new NodeIdentifierWithPredicates( nodeName1, key1, "foo" );
+ verifyNodeIdentifierWithPredicates( "NodeIdentifierWithPredicates", node1, nodeName1, key1, "foo" );
+
+ NodeIdentifierWithPredicates node2 = new NodeIdentifierWithPredicates( nodeName1, key1, "foo" );
+
+ assertEquals( "hashCode", node1.hashCode(), node2.hashCode() );
+ assertEquals( "equals", true, node1.equals( node2 ) );
+
+ assertEquals( "equals", false,
+ node1.equals( new NodeIdentifierWithPredicates( nodeName2, key1, "foo" ) ) );
+ assertEquals( "equals", false,
+ node1.equals( new NodeIdentifierWithPredicates( nodeName1, key2, "foo" ) ) );
+ assertEquals( "equals", false,
+ node1.equals( new NodeIdentifierWithPredicates( nodeName1, key1, "bar" ) ) );
+ assertEquals( "equals", false, node1.equals( new Object() ) );
+
+ assertNotNull( node1.toString() ); // for code coverage
+
+ NodeIdentifierWithPredicates node3 = new NodeIdentifierWithPredicates( nodeName1,
+ ImmutableMap.<QName, Object>builder().put( key1, 10 ).put( key2, 20 ).build() );
+
+ NodeIdentifierWithPredicates node4 = new NodeIdentifierWithPredicates( nodeName1,
+ ImmutableMap.<QName, Object>builder().put( key1, 10 ).put( key2, 20 ).build() );
+
+ assertEquals( "hashCode", node3.hashCode(), node4.hashCode() );
+ assertEquals( "equals", true, node3.equals( node4 ) );
+
+ assertEquals( "equals", false, node3.equals( node1 ) );
+ assertEquals( "equals", false,
+ node1.equals( new NodeIdentifierWithPredicates( nodeName1,
+ ImmutableMap.<QName, Object>builder().put( key1, 10 ).put( key3, 20 ).build() ) ) );
+
+ node1 = new NodeIdentifierWithPredicates( nodeName1, key1, new byte[]{1,2} );
+ node2 = new NodeIdentifierWithPredicates( nodeName1, key1, new byte[]{1,2} );
+
+ assertEquals( "hashCode", node1.hashCode(), node2.hashCode() );
+ assertEquals( "equals", true, node1.equals( node2 ) );
+
+ assertEquals( "equals", false,
+ node1.equals( new NodeIdentifierWithPredicates( nodeName1, key1, new byte[]{1,3} ) ) );
+ assertEquals( "equals", false,
+ node1.equals( new NodeIdentifierWithPredicates( nodeName1, key1, new byte[]{1} ) ) );
+ assertEquals( "equals", false,
+ node1.equals( new NodeIdentifierWithPredicates( nodeName1, key1, new byte[]{1,2,3} ) ) );
+ }
+
+ @Test
+ public void testNodeWithValue() {
+
+ NodeWithValue node1 = new NodeWithValue( nodeName1, "foo" );
+ assertEquals( "getNodeType", nodeName1, node1.getNodeType() );
+ assertEquals( "getValue", "foo", node1.getValue() );
+
+ NodeWithValue node2 = new NodeWithValue( nodeName1, "foo" );
+
+ assertEquals( "hashCode", node1.hashCode(), node2.hashCode() );
+ assertEquals( "equals", true, node1.equals( node2 ) );
+
+ assertEquals( "equals", false, node1.equals( new NodeWithValue( nodeName1, "bar" ) ) );
+ assertEquals( "equals", false, node1.equals( new NodeWithValue( nodeName2, "foo" ) ) );
+ assertEquals( "equals", false, node1.equals( new Object() ) );
+
+ assertNotNull( node1.toString() ); // for code coverage
+
+ NodeWithValue node3 = new NodeWithValue( nodeName1, new byte[]{1,2} );
+ NodeWithValue node4 = new NodeWithValue( nodeName1, new byte[]{1,2} );
+
+ assertEquals( "hashCode", node3.hashCode(), node4.hashCode() );
+ assertEquals( "equals", true, node3.equals( node4 ) );
+
+ assertEquals( "equals", false, node3.equals( new NodeWithValue( nodeName1, new byte[]{1,3} ) ) );
+ assertEquals( "equals", false, node3.equals( node1 ) );
+ }
+
+ @Test
+ public void testNodeIdentifier() {
+
+ NodeIdentifier node1 = new NodeIdentifier( nodeName1 );
+ assertEquals( "getNodeType", nodeName1, node1.getNodeType() );
+
+ NodeIdentifier node2 = new NodeIdentifier( nodeName1 );
+
+ assertEquals( "hashCode", node1.hashCode(), node2.hashCode() );
+ assertEquals( "equals", true, node1.equals( node2 ) );
+ assertEquals( "compareTo", 0, node1.compareTo( node2 ) );
+
+ assertEquals( "equals", false, node1.equals( new NodeIdentifier( nodeName3 ) ) );
+ assertEquals( "compareTo", true, node1.compareTo( new NodeIdentifier( nodeName3 ) ) != 0 );
+ assertEquals( "equals", false, node1.equals( new Object() ) );
+
+ assertNotNull( node1.toString() ); // for code coverage
+ }
+
+ @Test
+ public void testAugmentationIdentifier() {
+
+ AugmentationIdentifier node1 = new AugmentationIdentifier( Sets.newHashSet( nodeName1, nodeName2 ) );
+ assertEquals( "getPossibleChildNames", Sets.newHashSet( nodeName1, nodeName2 ), node1.getPossibleChildNames() );
+
+ AugmentationIdentifier node2 = new AugmentationIdentifier( Sets.newHashSet( nodeName2, nodeName1 ) );
+
+ assertEquals( "hashCode", node1.hashCode(), node2.hashCode() );
+ assertEquals( "equals", true, node1.equals( node2 ) );
+
+ assertEquals( "equals", false,
+ node1.equals( new AugmentationIdentifier( Sets.newHashSet( nodeName1, nodeName3 ) ) ) );
+ assertEquals( "equals", false,
+ node1.equals( new AugmentationIdentifier( Sets.newHashSet( nodeName1 ) ) ) );
+ assertEquals( "equals", false, node1.equals( new Object() ) );
+
+ assertNotNull( node1.toString() ); // for code coverage
+ }
+}
</build>
<dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>util</artifactId>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>yang-common</artifactId>
@Override
public String deserialize(String stringRepresentation) {
- return stringRepresentation;
+ return stringRepresentation == null ? "" :stringRepresentation;
}
@Override
} else { // CompositeNode
for (Node<?> child : ((CompositeNode) data).getValue()) {
DataSchemaNode childSchema = null;
- if (schema != null) {
+ if (schema instanceof DataNodeContainer) {
childSchema = findFirstSchemaForNode(child, ((DataNodeContainer) schema).getChildNodes());
if (logger.isDebugEnabled()) {
if (childSchema == null) {
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedAttrNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedValueAttrNode;
public class ImmutableLeafNodeBuilder<T> extends AbstractImmutableNormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> {
return new ImmutableLeafNode<>(getNodeIdentifier(), getValue(), getAttributes());
}
- private static final class ImmutableLeafNode<T> extends AbstractImmutableNormalizedAttrNode<InstanceIdentifier.NodeIdentifier, T> implements LeafNode<T> {
+ private static final class ImmutableLeafNode<T> extends AbstractImmutableNormalizedValueAttrNode<InstanceIdentifier.NodeIdentifier, T> implements LeafNode<T> {
ImmutableLeafNode(final InstanceIdentifier.NodeIdentifier nodeIdentifier, final T value, final Map<QName, String> attributes) {
super(nodeIdentifier, value, attributes);
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedAttrNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedValueAttrNode;
import com.google.common.base.Preconditions;
return new ImmutableLeafSetEntryNode<>(getNodeIdentifier(), getValue(), getAttributes());
}
- private static final class ImmutableLeafSetEntryNode<T> extends AbstractImmutableNormalizedAttrNode<InstanceIdentifier.NodeWithValue, T> implements LeafSetEntryNode<T> {
+ private static final class ImmutableLeafSetEntryNode<T> extends AbstractImmutableNormalizedValueAttrNode<InstanceIdentifier.NodeWithValue, T> implements LeafSetEntryNode<T> {
ImmutableLeafSetEntryNode(final InstanceIdentifier.NodeWithValue nodeIdentifier, final T value, final Map<QName, String> attributes) {
super(nodeIdentifier, value, attributes);
package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
import java.util.Collections;
-import java.util.LinkedHashMap;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.util.MapAdaptor;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedValueNode;
import com.google.common.base.Optional;
import com.google.common.collect.Iterables;
public class ImmutableLeafSetNodeBuilder<T> implements ListNodeBuilder<T, LeafSetEntryNode<T>> {
- private Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> value;
+ private final Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> value;
private InstanceIdentifier.NodeIdentifier nodeIdentifier;
- private boolean dirty;
protected ImmutableLeafSetNodeBuilder() {
- value = new LinkedHashMap<>();
- dirty = false;
+ value = new HashMap<>();
}
protected ImmutableLeafSetNodeBuilder(final ImmutableLeafSetNode<T> node) {
nodeIdentifier = node.getIdentifier();
- value = node.getChildren();
- dirty = true;
+ value = MapAdaptor.getDefaultInstance().takeSnapshot(node.children);
}
public static <T> ListNodeBuilder<T, LeafSetEntryNode<T>> create() {
return new ImmutableLeafSetNodeBuilder<T>((ImmutableLeafSetNode<T>) node);
}
- private void checkDirty() {
- if (dirty) {
- value = new LinkedHashMap<>(value);
- dirty = false;
- }
- }
-
@Override
public ListNodeBuilder<T, LeafSetEntryNode<T>> withChild(final LeafSetEntryNode<T> child) {
- checkDirty();
this.value.put(child.getIdentifier(), child);
return this;
}
@Override
public ListNodeBuilder<T, LeafSetEntryNode<T>> withoutChild(final PathArgument key) {
- checkDirty();
this.value.remove(key);
return this;
}
@Override
public LeafSetNode<T> build() {
- dirty = true;
- return new ImmutableLeafSetNode<>(nodeIdentifier, value);
+ return new ImmutableLeafSetNode<>(nodeIdentifier, MapAdaptor.getDefaultInstance().optimize(value));
}
@Override
@Override
public ListNodeBuilder<T, LeafSetEntryNode<T>> withValue(final List<LeafSetEntryNode<T>> value) {
- checkDirty();
for (final LeafSetEntryNode<T> leafSetEntry : value) {
withChild(leafSetEntry);
}
}
protected final static class ImmutableLeafSetNode<T> extends
- AbstractImmutableNormalizedNode<InstanceIdentifier.NodeIdentifier, Iterable<LeafSetEntryNode<T>>> implements
+ AbstractImmutableNormalizedValueNode<InstanceIdentifier.NodeIdentifier, Iterable<LeafSetEntryNode<T>>> implements
Immutable, LeafSetNode<T> {
private final Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> children;
return children.hashCode();
}
- private Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> getChildren() {
- return Collections.unmodifiableMap(children);
- }
-
@Override
protected boolean valueEquals(final AbstractImmutableNormalizedNode<?, ?> other) {
return children.equals(((ImmutableLeafSetNode<?>) other).children);
*/
package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
-import java.util.LinkedHashMap;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.util.MapAdaptor;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
public class ImmutableMapNodeBuilder
implements CollectionNodeBuilder<MapEntryNode, MapNode> {
- private Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> value;
+ private final Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> value;
private InstanceIdentifier.NodeIdentifier nodeIdentifier;
- private boolean dirty = false;
protected ImmutableMapNodeBuilder() {
- this.value = new LinkedHashMap<>();
- this.dirty = false;
+ this.value = new HashMap<>();
}
protected ImmutableMapNodeBuilder(final ImmutableMapNode node) {
this.nodeIdentifier = node.getIdentifier();
- this.value = node.children;
- this.dirty = true;
+ this.value = MapAdaptor.getDefaultInstance().takeSnapshot(node.children);
}
public static CollectionNodeBuilder<MapEntryNode, MapNode> create() {
return new ImmutableMapNodeBuilder((ImmutableMapNode) node);
}
- private void checkDirty() {
- if (dirty) {
- value = new LinkedHashMap<>(value);
- dirty = false;
- }
- }
-
@Override
public CollectionNodeBuilder<MapEntryNode, MapNode> withChild(final MapEntryNode child) {
- checkDirty();
this.value.put(child.getIdentifier(), child);
return this;
}
@Override
public CollectionNodeBuilder<MapEntryNode, MapNode> withoutChild(final InstanceIdentifier.PathArgument key) {
- checkDirty();
this.value.remove(key);
return this;
}
@Override
public MapNode build() {
- dirty = true;
- return new ImmutableMapNode(nodeIdentifier, value);
+ return new ImmutableMapNode(nodeIdentifier, MapAdaptor.getDefaultInstance().optimize(value));
}
@Override
ImmutableMapNode(final InstanceIdentifier.NodeIdentifier nodeIdentifier,
final Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> children) {
- super(nodeIdentifier, Iterables.unmodifiableIterable(children.values()));
+ super(nodeIdentifier);
this.children = children;
}
return Optional.fromNullable(children.get(child));
}
+ @Override
+ public Iterable<MapEntryNode> getValue() {
+ return Iterables.unmodifiableIterable(children.values());
+ }
+
@Override
protected int valueHashCode() {
return children.hashCode();
ImmutableOrderedLeafSetNode(final InstanceIdentifier.NodeIdentifier nodeIdentifier,
final Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> children) {
- super(nodeIdentifier, Iterables.unmodifiableIterable(children.values()));
+ super(nodeIdentifier);
this.children = children;
}
// TODO Auto-generated method stub
return 0;
}
+
+ @Override
+ public Iterable<LeafSetEntryNode<T>> getValue() {
+ return Iterables.unmodifiableIterable(children.values());
+ }
}
@Override
ImmutableOrderedMapNode(final InstanceIdentifier.NodeIdentifier nodeIdentifier,
final Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> children) {
- super(nodeIdentifier, Iterables.unmodifiableIterable(children.values()));
+ super(nodeIdentifier);
this.children = children;
}
public int getSize() {
return children.size();
}
+
+ @Override
+ public Iterable<MapEntryNode> getValue() {
+ return Iterables.unmodifiableIterable(children.values());
+ }
}
}
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedValueNode;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
}
protected static final class ImmutableUnkeyedListNode extends
- AbstractImmutableNormalizedNode<InstanceIdentifier.NodeIdentifier, Iterable<UnkeyedListEntryNode>>
+ AbstractImmutableNormalizedValueNode<InstanceIdentifier.NodeIdentifier, Iterable<UnkeyedListEntryNode>>
implements Immutable, UnkeyedListNode {
private final ImmutableList<UnkeyedListEntryNode> children;
public AbstractImmutableDataContainerNode(
final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> children, final K nodeIdentifier) {
- super(nodeIdentifier, Iterables.unmodifiableIterable(children.values()));
+ super(nodeIdentifier);
this.children = children;
}
return Optional.<DataContainerChild<? extends PathArgument, ?>> fromNullable(children.get(child));
}
+ @Override
+ public final Iterable<DataContainerChild<? extends PathArgument, ?>> getValue() {
+ return Iterables.unmodifiableIterable(children.values());
+ }
+
@Override
protected int valueHashCode() {
return children.hashCode();
implements NormalizedNode<K, V>, Immutable {
private final K nodeIdentifier;
- private final V value;
- protected AbstractImmutableNormalizedNode(final K nodeIdentifier, final V value) {
+ protected AbstractImmutableNormalizedNode(final K nodeIdentifier) {
this.nodeIdentifier = Preconditions.checkNotNull(nodeIdentifier, "nodeIdentifier");
- this.value = Preconditions.checkNotNull(value, "value");
}
@Override
return getNodeType();
}
- @Override
- public final V getValue() {
- return value;
- }
-
@Override
public final V setValue(final V value) {
throw new UnsupportedOperationException("Immutable");
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.ImmutableMap;
-public abstract class AbstractImmutableNormalizedAttrNode<K extends InstanceIdentifier.PathArgument,V>
- extends AbstractImmutableNormalizedNode<K, V>
+public abstract class AbstractImmutableNormalizedValueAttrNode<K extends InstanceIdentifier.PathArgument,V>
+ extends AbstractImmutableNormalizedValueNode<K, V>
implements AttributesContainer {
private final Map<QName, String> attributes;
- protected AbstractImmutableNormalizedAttrNode(final K nodeIdentifier, final V value, final Map<QName, String> attributes) {
+ protected AbstractImmutableNormalizedValueAttrNode(final K nodeIdentifier, final V value, final Map<QName, String> attributes) {
super(nodeIdentifier, value);
this.attributes = ImmutableMap.copyOf(attributes);
}
--- /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.data.impl.schema.nodes;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import com.google.common.base.Preconditions;
+
+public abstract class AbstractImmutableNormalizedValueNode<K extends InstanceIdentifier.PathArgument,V>
+ extends AbstractImmutableNormalizedNode<K, V> {
+
+ private final V value;
+
+ protected AbstractImmutableNormalizedValueNode(final K nodeIdentifier, final V value) {
+ super(nodeIdentifier);
+ this.value = Preconditions.checkNotNull(value, "value");
+ }
+
+ @Override
+ public final V getValue() {
+ return value;
+ }
+}
import org.opendaylight.yangtools.yang.common.QName;
/**
+ *
* The ChoiceNode defines a set of alternatives. It consists of a number of
* branches defined as ChoiceCaseNode objects.
*/
/**
* Returns cases of choice.
- *
+ *
* @return set of ChoiceCaseNode objects defined in this node which
* represents set of arguments of the YANG <code>case</code>
* substatement of the <code>choice</code> statement
Set<ChoiceCaseNode> getCases();
/**
- *
+ *
* Returns the concrete case according to specified Q name.
- *
+ *
* @param name
* QName of seeked Choice Case Node
* @return child case node of this Choice if child with given name is
/**
* Returns the concrete case according to specified name.
- *
+ *
* @param name
* name of seeked child as String
* @return child case node (or local name of case node) of this Choice if
ChoiceCaseNode getCaseNodeByName(String name);
/**
- *
+ *
* Returns name of case which is in the choice specified as default
- *
+ *
* @return string with the name of case which is specified in the argument
* of the YANG <code>default</code> substatement of
* <code>choice</code> statement.
package org.opendaylight.yangtools.yang.model.api;
/**
+ *
+ * Data Schema Node represents abstract supertype from which all data tree
+ * definitions are derived.
*
* Contains the method which are used for getting metadata from the schema nodes
* which contains data.
*
+ * @see ContainerSchemaNode
+ * @see ListSchemaNode
+ * @see LeafListSchemaNode
+ * @see ChoiceNode
+ * @see ChoiceCaseNode
+ * @see LeafSchemaNode
+ * @see AnyXmlSchemaNode
+ *
+ *
*/
public interface DataSchemaNode extends SchemaNode {
*/
package org.opendaylight.yangtools.yang.model.util;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
+import com.google.common.base.Optional;
+
/**
* The Abstract Integer class defines implementation of IntegerTypeDefinition
* interface which represents SIGNED Integer values defined in Yang language. <br>
private final List<RangeConstraint> rangeStatements;
/**
- * @param name
- * @param description
- * @param minRange
- * @param maxRange
- * @param units
+ * Construct SignedInteger
+ *
+ * @param name Name of type
+ * @param description Description of type
+ * @param minRange Minimal range
+ * @param maxRange Maxium range
+ * @param units Units
*/
- public AbstractSignedInteger(final QName name, final String description, final Number minRange,
+ protected AbstractSignedInteger(final QName name, final String description, final Number minRange,
final Number maxRange, final String units) {
this.name = name;
this.path = SchemaPath.create(Collections.singletonList(name), true);
this.description = description;
this.units = units;
- this.rangeStatements = new ArrayList<RangeConstraint>();
final String rangeDescription = "Integer values between " + minRange + " and " + maxRange + ", inclusively.";
- this.rangeStatements.add(BaseConstraints.rangeConstraint(minRange, maxRange, rangeDescription,
- "https://tools.ietf.org/html/rfc6020#section-9.2.4"));
+ this.rangeStatements = Collections.singletonList(BaseConstraints.newRangeConstraint(minRange, maxRange, Optional.of(rangeDescription),
+ Optional.of("https://tools.ietf.org/html/rfc6020#section-9.2.4")));
}
@Override
*/
package org.opendaylight.yangtools.yang.model.util;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
+import com.google.common.base.Optional;
+
/**
* The Abstract Integer class defines implementation of IntegerTypeDefinition
* interface which represents UNSIGNED Integer values defined in Yang language. <br>
private final List<RangeConstraint> rangeStatements;
/**
+ * Construct Unsigned Integer
*
- * @param name
- * @param description
- * @param maxRange
- * @param units
+ * @param name Name of type
+ * @param description Description of type
+ * @param maxRange Maximum value
+ * @param units Units
*/
public AbstractUnsignedInteger(final QName name, final String description, final Number maxRange, final String units) {
this.name = name;
this.path = SchemaPath.create(Collections.singletonList(name), true);
this.description = description;
this.units = units;
- this.rangeStatements = new ArrayList<RangeConstraint>();
final String rangeDescription = "Integer values between " + MIN_VALUE + " and " + maxRange + ", inclusively.";
- this.rangeStatements.add(BaseConstraints.rangeConstraint(MIN_VALUE, maxRange, rangeDescription,
- "https://tools.ietf.org/html/rfc6020#section-9.2.4"));
+ this.rangeStatements = Collections.singletonList(BaseConstraints.newRangeConstraint(MIN_VALUE, maxRange, Optional.of(rangeDescription),
+ Optional.of("https://tools.ietf.org/html/rfc6020#section-9.2.4")));
}
@Override
import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
+import com.google.common.base.Optional;
+
+/**
+ * Utility class which provides factory methods to construct Constraints.
+ *
+ * Provides static factory methods which constructs instances of
+ * <ul>
+ * <li>{@link LengthConstraint} - {@link #lengthConstraint(Number, Number, String, String)}
+ * <li>{@link RangeConstraint} - {@link #rangeConstraint(Number, Number, String, String)}
+ * <li>{@link PatternConstraint} - {@link #patternConstraint(String, String, String)}
+ * </ul>
+ */
public final class BaseConstraints {
private BaseConstraints() {
}
- public static LengthConstraint lengthConstraint(final Number min, final Number max, final String description,
- final String reference) {
+
+ /**
+ * Creates a {@link LengthConstraint}.
+ *
+ * Creates an instance of Length constraint based on supplied parameters
+ * with additional behaviour:
+ *
+ * <ul>
+ * <li>{@link LengthConstraint#getErrorAppTag()} returns <code>length-out-of-specified-bounds</code>
+ * <li>{@link LengthConstraint#getErrorMessage() returns <code>The argument is out of bounds <<i>min</i>, <i>max</i> ></code>
+ * </ul>
+ *
+ * @see LengthConstraint
+ *
+ * @param min length-restricting lower bound value. The value MUST NOT be negative.
+ * @param max length-restricting upper bound value. The value MUST NOT be negative.
+ * @param description Description associated with constraint. {@link Optional#absent()} if description is undefined.
+ * @param reference Reference associated with constraint. {@link Optional#absent()} if reference is undefined.
+ * @return Instance of {@link LengthConstraint}
+ */
+ public static LengthConstraint newLengthConstraint(final Number min, final Number max, final Optional<String> description,
+ final Optional<String> reference) {
return new LengthConstraintImpl(min, max, description, reference);
}
- public static RangeConstraint rangeConstraint(final Number min, final Number max, final String description,
- final String reference) {
+ /**
+ * Creates a {@link RangeConstraint}.
+ *
+ * Creates an instance of Range constraint based on supplied parameters
+ * with additional behaviour:
+ *
+ * <ul>
+ * <li>{@link RangeConstraint#getErrorAppTag()} returns <code>range-out-of-specified-bounds</code>
+ * <li>{@link RangeConstraint#getErrorMessage() returns <code>The argument is out of bounds <<i>min</i>, <i>max</i> ></code>
+ * </ul>
+ *
+ *
+ * @see RangeConstraint
+ *
+ * @param min value-restricting lower bound value. The value MUST NOT Be null.
+ * @param max value-restricting upper bound value. The value MUST NOT Be null.
+ * @param description Description associated with constraint. {@link Optional#absent()} if description is undefined.
+ * @param reference Reference associated with constraint. {@link Optional#absent()} if reference is undefined.
+ * @return Instance of {@link RangeConstraint}
+ */
+ public static RangeConstraint newRangeConstraint(final Number min, final Number max, final Optional<String> description,
+ final Optional<String> reference) {
return new RangeConstraintImpl(min, max, description, reference);
}
- public static PatternConstraint patternConstraint(final String pattern, final String description,
- final String reference) {
+
+ /**
+ * Creates a {@link PatternConstraint}.
+ *
+ * Creates an instance of Pattern constraint based on supplied parameters
+ * with additional behaviour:
+ *
+ * <ul>
+ * <li>{@link PatternConstraint#getErrorAppTag()} returns <code>invalid-regular-expression</code>
+ * </ul>
+ *
+ * @see PatternConstraint
+ *
+ * @param pattern Regular expression, MUST NOT BE null.
+ * @param description Description associated with constraint.
+ * @param reference Reference associated with constraint.
+ * @returnInstance of {@link PatternConstraint}
+ */
+ public static PatternConstraint newPatternConstraint(final String pattern, final Optional<String> description,
+ final Optional<String> reference) {
return new PatternConstraintImpl(pattern, description, reference);
}
- private static final class LengthConstraintImpl implements LengthConstraint {
-
- private final Number min;
- private final Number max;
-
- private final String description;
- private final String reference;
-
- private final String errorAppTag;
- private final String errorMessage;
- public LengthConstraintImpl(Number min, Number max, final String description, final String reference) {
- super();
- this.min = min;
- this.max = max;
- this.description = description;
- this.reference = reference;
-
- this.errorAppTag = "length-out-of-specified-bounds";
- this.errorMessage = "The argument is out of bounds <" + min + ", " + max + ">";
- }
-
- @Override
- public String getDescription() {
- return description;
- }
-
- @Override
- public String getErrorAppTag() {
- return errorAppTag;
- }
-
- @Override
- public String getErrorMessage() {
- return errorMessage;
- }
-
- @Override
- public String getReference() {
- return reference;
- }
-
- @Override
- public Number getMin() {
- return min;
- }
-
- @Override
- public Number getMax() {
- return max;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((description == null) ? 0 : description.hashCode());
- result = prime * result + ((errorAppTag == null) ? 0 : errorAppTag.hashCode());
- result = prime * result + ((errorMessage == null) ? 0 : errorMessage.hashCode());
- result = prime * result + ((max == null) ? 0 : max.hashCode());
- result = prime * result + ((min == null) ? 0 : min.hashCode());
- result = prime * result + ((reference == null) ? 0 : reference.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- final LengthConstraintImpl other = (LengthConstraintImpl) obj;
- if (description == null) {
- if (other.description != null) {
- return false;
- }
- } else if (!description.equals(other.description)) {
- return false;
- }
- if (errorAppTag == null) {
- if (other.errorAppTag != null) {
- return false;
- }
- } else if (!errorAppTag.equals(other.errorAppTag)) {
- return false;
- }
- if (errorMessage == null) {
- if (other.errorMessage != null) {
- return false;
- }
- } else if (!errorMessage.equals(other.errorMessage)) {
- return false;
- }
- if (max != other.max) {
- return false;
- }
- if (min != other.min) {
- return false;
- }
- if (reference == null) {
- if (other.reference != null) {
- return false;
- }
- } else if (!reference.equals(other.reference)) {
- return false;
- }
- return true;
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("LengthConstraintImpl [min=");
- builder.append(min);
- builder.append(", max=");
- builder.append(max);
- builder.append(", description=");
- builder.append(description);
- builder.append(", errorAppTag=");
- builder.append(errorAppTag);
- builder.append(", reference=");
- builder.append(reference);
- builder.append(", errorMessage=");
- builder.append(errorMessage);
- builder.append("]");
- return builder.toString();
- }
+ /**
+ * Creates a {@link LengthConstraint}.
+ *
+ * Creates an instance of Length constraint based on supplied parameters
+ * with additional behaviour:
+ *
+ * <ul>
+ * <li>{@link LengthConstraint#getErrorAppTag()} returns <code>length-out-of-specified-bounds</code>
+ * <li>{@link LengthConstraint#getErrorMessage() returns <code>The argument is out of bounds <<i>min</i>, <i>max</i> ></code>
+ * </ul>
+ *
+ * @see LengthConstraint
+ *
+ * @param min length-restricting lower bound value. The value MUST NOT be negative.
+ * @param max length-restricting upper bound value. The value MUST NOT be negative.
+ * @param description Description associated with constraint.
+ * @param reference Reference associated with constraint.
+ * @return Instance of {@link LengthConstraint}
+ * @deprecated Use {@link #newLengthConstraint(Number, Number, Optional, Optional)} instead.
+ */
+ @Deprecated
+ public static LengthConstraint lengthConstraint(final Number min, final Number max, final String description,
+ final String reference) {
+ return newLengthConstraint(min, max, Optional.fromNullable(description), Optional.fromNullable(reference));
}
- private static final class RangeConstraintImpl implements RangeConstraint {
- private final Number min;
- private final Number max;
-
- private final String description;
- private final String reference;
-
- private final String errorAppTag;
- private final String errorMessage;
-
- public RangeConstraintImpl(Number min, Number max, String description, String reference) {
- super();
- this.min = min;
- this.max = max;
- this.description = description;
- this.reference = reference;
-
- this.errorAppTag = "range-out-of-specified-bounds";
- this.errorMessage = "The argument is out of bounds <" + min + ", " + max + ">";
- }
-
- @Override
- public String getDescription() {
- return description;
- }
-
- @Override
- public String getErrorAppTag() {
- return errorAppTag;
- }
-
- @Override
- public String getErrorMessage() {
- return errorMessage;
- }
-
- @Override
- public String getReference() {
- return reference;
- }
-
- @Override
- public Number getMin() {
- return min;
- }
-
- @Override
- public Number getMax() {
- return max;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((description == null) ? 0 : description.hashCode());
- result = prime * result + ((errorAppTag == null) ? 0 : errorAppTag.hashCode());
- result = prime * result + ((errorMessage == null) ? 0 : errorMessage.hashCode());
- result = prime * result + ((max == null) ? 0 : max.hashCode());
- result = prime * result + ((min == null) ? 0 : min.hashCode());
- result = prime * result + ((reference == null) ? 0 : reference.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- final RangeConstraintImpl other = (RangeConstraintImpl) obj;
- if (description == null) {
- if (other.description != null) {
- return false;
- }
- } else if (!description.equals(other.description)) {
- return false;
- }
- if (errorAppTag == null) {
- if (other.errorAppTag != null) {
- return false;
- }
- } else if (!errorAppTag.equals(other.errorAppTag)) {
- return false;
- }
- if (errorMessage == null) {
- if (other.errorMessage != null) {
- return false;
- }
- } else if (!errorMessage.equals(other.errorMessage)) {
- return false;
- }
- if (max == null) {
- if (other.max != null) {
- return false;
- }
- } else if (!max.equals(other.max)) {
- return false;
- }
- if (min == null) {
- if (other.min != null) {
- return false;
- }
- } else if (!min.equals(other.min)) {
- return false;
- }
- if (reference == null) {
- if (other.reference != null) {
- return false;
- }
- } else if (!reference.equals(other.reference)) {
- return false;
- }
- return true;
- }
-
- @Override
- public String toString() {
- final StringBuilder builder = new StringBuilder();
- builder.append("RangeConstraintImpl [min=");
- builder.append(min);
- builder.append(", max=");
- builder.append(max);
- builder.append(", description=");
- builder.append(description);
- builder.append(", reference=");
- builder.append(reference);
- builder.append(", errorAppTag=");
- builder.append(errorAppTag);
- builder.append(", errorMessage=");
- builder.append(errorMessage);
- builder.append("]");
- return builder.toString();
- }
+ /**
+ * Creates a {@link RangeConstraint}.
+ *
+ * Creates an instance of Range constraint based on supplied parameters
+ * with additional behaviour:
+ *
+ * <ul>
+ * <li>{@link RangeConstraint#getErrorAppTag()} returns <code>range-out-of-specified-bounds</code>
+ * <li>{@link RangeConstraint#getErrorMessage() returns <code>The argument is out of bounds <<i>min</i>, <i>max</i> ></code>
+ * </ul>
+ *
+ *
+ * @see RangeConstraint
+ *
+ * @param min value-restricting lower bound value. The value MUST NOT Be null.
+ * @param max value-restricting upper bound value. The value MUST NOT Be null.
+ * @param description Description associated with constraint.
+ * @param reference Reference associated with constraint.
+ * @return Instance of {@link RangeConstraint}
+ * @deprecated Use {@link #newRangeConstraint(Number, Number, Optional, Optional)} instead.
+ */
+ @Deprecated
+ public static RangeConstraint rangeConstraint(final Number min, final Number max, final String description,
+ final String reference) {
+ return newRangeConstraint(min, max, Optional.fromNullable(description), Optional.fromNullable(reference));
}
- private static final class PatternConstraintImpl implements PatternConstraint {
-
- private final String regex;
- private final String description;
- private final String reference;
-
- private final String errorAppTag;
- private final String errorMessage;
-
- public PatternConstraintImpl(final String regex, final String description, final String reference) {
- super();
- this.regex = regex;
- this.description = description;
- this.reference = reference;
-
- errorAppTag = "invalid-regular-expression";
- // TODO: add erro message
- errorMessage = "";
- }
-
- @Override
- public String getDescription() {
- return description;
- }
-
- @Override
- public String getErrorAppTag() {
- return errorAppTag;
- }
-
- @Override
- public String getErrorMessage() {
- return errorMessage;
- }
-
- @Override
- public String getReference() {
- return reference;
- }
-
- @Override
- public String getRegularExpression() {
- return regex;
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((description == null) ? 0 : description.hashCode());
- result = prime * result + ((errorAppTag == null) ? 0 : errorAppTag.hashCode());
- result = prime * result + ((errorMessage == null) ? 0 : errorMessage.hashCode());
- result = prime * result + ((reference == null) ? 0 : reference.hashCode());
- result = prime * result + ((regex == null) ? 0 : regex.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(final Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- final PatternConstraintImpl other = (PatternConstraintImpl) obj;
- if (description == null) {
- if (other.description != null) {
- return false;
- }
- } else if (!description.equals(other.description)) {
- return false;
- }
- if (errorAppTag == null) {
- if (other.errorAppTag != null) {
- return false;
- }
- } else if (!errorAppTag.equals(other.errorAppTag)) {
- return false;
- }
- if (errorMessage == null) {
- if (other.errorMessage != null) {
- return false;
- }
- } else if (!errorMessage.equals(other.errorMessage)) {
- return false;
- }
- if (reference == null) {
- if (other.reference != null) {
- return false;
- }
- } else if (!reference.equals(other.reference)) {
- return false;
- }
- if (regex == null) {
- if (other.regex != null) {
- return false;
- }
- } else if (!regex.equals(other.regex)) {
- return false;
- }
- return true;
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("PatternConstraintImpl [regex=");
- builder.append(regex);
- builder.append(", description=");
- builder.append(description);
- builder.append(", reference=");
- builder.append(reference);
- builder.append(", errorAppTag=");
- builder.append(errorAppTag);
- builder.append(", errorMessage=");
- builder.append(errorMessage);
- builder.append("]");
- return builder.toString();
- }
+ /**
+ * Creates a {@link PatternConstraint}.
+ *
+ * Creates an instance of Range constraint based on supplied parameters
+ * with additional behaviour:
+ *
+ * <ul>
+ * <li>{@link PatternConstraint#getErrorAppTag()} returns <code>invalid-regular-expression</code>
+ * </ul>
+ *
+ *
+ * @see PatternConstraint
+ *
+ * @param pattern Regular expression, MUST NOT
+ * @param description Description associated with constraint.
+ * @param reference Reference associated with constraint.
+ * @return Instance of {@link PatternConstraint}
+ * @deprecated Use {@link #newPatternConstraint(String, Optional, Optional)} Instead.
+ */
+ @Deprecated
+ public static PatternConstraint patternConstraint(final String pattern, final String description,
+ final String reference) {
+ return newPatternConstraint(pattern, Optional.fromNullable(description), Optional.fromNullable(reference));
}
}
import java.util.Collections;
import java.util.Date;
import java.util.List;
+import java.util.Set;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Utility methods and constants to work with built-in YANG types
+ *
+ *
+ */
public final class BaseTypes {
private BaseTypes() {
}
public static final URI BASE_TYPES_NAMESPACE = URI.create("urn:ietf:params:xml:ns:yang:1");
+
public static final QName BINARY_QNAME = constructQName("binary");
public static final QName BITS_QNAME = constructQName("bits");
public static final QName BOOLEAN_QNAME = constructQName("boolean");
public static final QName DECIMAL64_QNAME = constructQName("decimal64");
public static final QName EMPTY_QNAME = constructQName("empty");
public static final QName ENUMERATION_QNAME = constructQName("enumeration");
+ public static final QName IDENTITYREF_QNAME = constructQName("identityref");
+ public static final QName INSTANCE_IDENTIFIER_QNAME = constructQName("instance-identifier");
public static final QName INT8_QNAME = constructQName("int8");
public static final QName INT16_QNAME = constructQName("int16");
public static final QName INT32_QNAME = constructQName("int32");
public static final QName UINT16_QNAME = constructQName("uint16");
public static final QName UINT32_QNAME = constructQName("uint32");
public static final QName UINT64_QNAME = constructQName("uint64");
+ public static final QName UNION_QNAME = constructQName("union");
+
+ private static final Set<String> BUILD_IN_TYPES = ImmutableSet.<String> builder().add(BINARY_QNAME.getLocalName()) //
+ .add(BITS_QNAME.getLocalName()) //
+ .add(BOOLEAN_QNAME.getLocalName()) //
+ .add(DECIMAL64_QNAME.getLocalName()) //
+ .add(EMPTY_QNAME.getLocalName()) //
+ .add(ENUMERATION_QNAME.getLocalName()) //
+ .add(IDENTITYREF_QNAME.getLocalName()) //
+ .add(INSTANCE_IDENTIFIER_QNAME.getLocalName()) //
+ .add(INT8_QNAME.getLocalName()) //
+ .add(INT16_QNAME.getLocalName()) //
+ .add(INT32_QNAME.getLocalName()) //
+ .add(INT64_QNAME.getLocalName()) //
+ .add(LEAFREF_QNAME.getLocalName()) //
+ .add(STRING_QNAME.getLocalName()) //
+ .add(UINT8_QNAME.getLocalName()) //
+ .add(UINT16_QNAME.getLocalName()) //
+ .add(UINT32_QNAME.getLocalName()) //
+ .add(UINT64_QNAME.getLocalName()) //
+ .add(UNION_QNAME.getLocalName()) //
+ .build();
/**
* Construct QName for Built-in base Yang type. The namespace for built-in
}
/**
- * Creates Schema Path from Qname.
+ * Creates Schema Path from {@link QName}.
*
* @param typeName
* yang type QName
* @return Schema Path from Qname.
+ * @deprecated Use {@link SchemaPath#create(boolean, QName...)} instead.
*/
+ @Deprecated
public static SchemaPath schemaPath(final QName typeName) {
return SchemaPath.create(Collections.singletonList(typeName), true);
}
* @param revision
* Revision Date
* @return Schema Path
+ *
+ * @deprecated Use {@link SchemaPath#create(boolean, Iterable)} with QNames
+ * manually constructed.
*/
+ @Deprecated
public static SchemaPath schemaPath(final List<String> actualPath, final URI namespace, final Date revision) {
if (actualPath == null) {
throw new IllegalArgumentException("The actual path List MUST be specified.");
}
return SchemaPath.create(pathList, true);
}
+
+ /**
+ * Returns true if supplied type is representation of built-in YANG type as
+ * per RFC 6020.
+ *
+ * See package documentation for description of base types.
+ *
+ * @param type
+ * @return true if type is built-in YANG Types.
+ */
+ public static boolean isYangBuildInType(final String type) {
+ return BUILD_IN_TYPES.contains(type);
+ }
+
+ /**
+ * Returns default instance of built-in for supplied type
+ *
+ * See package documentation for description of base build-in types
+ * with default instance.
+ *
+ * @param typeName
+ * @return Returns default instance or {@link Optional#absent()} if default
+ * instance does not exists
+ *
+ */
+ public static Optional<TypeDefinition<?>> defaultBaseTypeFor(final String typeName) {
+ return Optional.<TypeDefinition<?>> fromNullable(defaultBaseTypeForImpl(typeName));
+ }
+
+ private static TypeDefinition<?> defaultBaseTypeForImpl(final String typeName) {
+ Preconditions.checkNotNull(typeName, "typeName must not be null.");
+
+ if (typeName.startsWith("int")) {
+ if ("int8".equals(typeName)) {
+ return Int8.getInstance();
+ } else if ("int16".equals(typeName)) {
+ return Int16.getInstance();
+ } else if ("int32".equals(typeName)) {
+ return Int32.getInstance();
+ } else if ("int64".equals(typeName)) {
+ return Int64.getInstance();
+ }
+ } else if (typeName.startsWith("uint")) {
+ if ("uint8".equals(typeName)) {
+ return Uint8.getInstance();
+ } else if ("uint16".equals(typeName)) {
+ return Uint16.getInstance();
+ } else if ("uint32".equals(typeName)) {
+ return Uint32.getInstance();
+ } else if ("uint64".equals(typeName)) {
+ return Uint64.getInstance();
+ }
+ } else if ("string".equals(typeName)) {
+ return StringType.getInstance();
+ } else if ("binary".equals(typeName)) {
+ return BinaryType.getInstance();
+ } else if ("boolean".equals(typeName)) {
+ return BooleanType.getInstance();
+ } else if ("empty".equals(typeName)) {
+ return EmptyType.getInstance();
+ } else if ("instance-identifier".equals(typeName)) {
+ return InstanceIdentifier.getInstance();
+ }
+ return null;
+ }
+
}
import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
+import com.google.common.base.Optional;
+
/**
* The <code>default</code> implementation of Binary Type Definition interface.
*
private static final String REFERENCE = "https://tools.ietf.org/html/rfc6020#section-9.8";
private static final String UNITS = "";
+ private final static QName QNAME = BaseTypes.BINARY_QNAME;
+
private static final BinaryType INSTANCE = new BinaryType();
- private final QName name = BaseTypes.BINARY_QNAME;
- private final SchemaPath path = SchemaPath.create(Collections.singletonList(name), true);
+ private final static SchemaPath PATH = SchemaPath.create(Collections.singletonList(QNAME), true);
private final List<Byte> bytes = Collections.emptyList();
private final List<LengthConstraint> lengthConstraints;
private BinaryType() {
this.lengthConstraints = Collections.singletonList(
- BaseConstraints.lengthConstraint(0, Long.MAX_VALUE, "", ""));
+ BaseConstraints.newLengthConstraint(0, Long.MAX_VALUE, Optional.of(""), Optional.of("")));
}
public static BinaryType getInstance() {
*/
@Override
public QName getQName() {
- return name;
+ return QNAME;
}
/*
*/
@Override
public SchemaPath getPath() {
- return path;
+ return PATH;
}
/*
int result = 1;
result = prime * result + ((bytes == null) ? 0 : bytes.hashCode());
result = prime * result + ((lengthConstraints == null) ? 0 : lengthConstraints.hashCode());
- result = prime * result + ((name == null) ? 0 : name.hashCode());
- result = prime * result + ((path == null) ? 0 : path.hashCode());
+ result = prime * result + QNAME.hashCode();
+ result = prime * result + PATH.hashCode();
return result;
}
} else if (!lengthConstraints.equals(other.lengthConstraints)) {
return false;
}
- if (name == null) {
- if (other.name != null) {
- return false;
- }
- } else if (!name.equals(other.name)) {
- return false;
- }
- if (path == null) {
- if (other.path != null) {
- return false;
- }
- } else if (!path.equals(other.path)) {
- return false;
- }
return true;
}
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("BinaryType [name=");
- builder.append(name);
- builder.append(", path=");
- builder.append(path);
+ builder.append(QNAME);
builder.append(", description=");
builder.append(DESCRIPTION);
builder.append(", reference=");
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
/**
* The <code>default</code> implementation of Bits Type Definition interface.
*
* @see BitsTypeDefinition
*/
public final class BitsType implements BitsTypeDefinition {
- private final QName name = BaseTypes.constructQName("bits");
+ private final static QName NAME = BaseTypes.BITS_QNAME;
+
private final SchemaPath path;
private final String description = "The bits built-in type represents a bit set. "
+ "That is, a bits value is a set of flags identified by small integer position "
* Instantiates Bits type as empty bits list.
*
* @param path
+ * @deprecated Use static factory method {@link #create(SchemaPath, List)} instead.
*/
+ @Deprecated
public BitsType(final SchemaPath path) {
super();
this.bits = Collections.emptyList();
- this.path = path;
+ this.path = Preconditions.checkNotNull(path,"path must not be null");
}
/**
*
* @param path
* @param bits
+ * @deprecated Use static factory method {@link #create(SchemaPath, List)} instead.
*/
+ @Deprecated
public BitsType(final SchemaPath path, final List<Bit> bits) {
super();
- this.bits = Collections.unmodifiableList(bits);
- this.path = path;
+ this.bits = ImmutableList.copyOf(bits);
+ this.path = Preconditions.checkNotNull(path,"path must not be null");
+ }
+
+ public static BitsType create(final SchemaPath path, final List<Bit> bits) {
+ return new BitsType(path,bits);
}
/*
*/
@Override
public QName getQName() {
- return name;
+ return NAME;
}
/*
int result = 1;
result = prime * result + ((bits == null) ? 0 : bits.hashCode());
result = prime * result + ((description == null) ? 0 : description.hashCode());
- result = prime * result + ((name == null) ? 0 : name.hashCode());
- result = prime * result + ((path == null) ? 0 : path.hashCode());
+ result = prime * result + NAME.hashCode();
+ result = prime * result + path.hashCode();
return result;
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
} else if (!description.equals(other.description)) {
return false;
}
- if (name == null) {
- if (other.name != null) {
- return false;
- }
- } else if (!name.equals(other.name)) {
- return false;
- }
+
if (path == null) {
if (other.path != null) {
return false;
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("BitsType [name=");
- builder.append(name);
+ builder.append(NAME);
builder.append(", path=");
builder.append(path);
builder.append(", description=");
private BooleanType() {
}
+ /**
+ * Returns default instance of boolean built-in type.
+ * @return default instance of boolean built-in type.
+ */
public static BooleanType getInstance() {
return INSTANCE;
}
import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+/**
+ * DataNodeIterator is iterator, which walks down whole YANG DataNodeContainer
+ * and walks all instances of {@link DataSchemaNode} present in subtree.
+ *
+ * Iterator instance is eagerly created, walking happens on initialization.
+ *
+ * Iteration is not ordered.
+ *
+ */
public class DataNodeIterator implements Iterator<DataSchemaNode> {
private final DataNodeContainer container;
traverse(this.container);
}
+ /**
+ * Returns list all containers present in subtree.
+ *
+ * @return Returns list all containers present in subtree.
+ */
public List<ContainerSchemaNode> allContainers() {
return allContainers;
}
+ /**
+ * Returns list all lists present in subtree.
+ *
+ * @return Returns list all containers present in subtree.
+ */
public List<ListSchemaNode> allLists() {
return allLists;
}
+ /**
+ * Returns list all choices present in subtree.
+ *
+ * @return Returns list all containers present in subtree.
+ */
public List<ChoiceNode> allChoices() {
return allChoices;
}
+ /**
+ * Returns list all groupings present in subtree.
+ *
+ * @return Returns list all containers present in subtree.
+ */
public List<GroupingDefinition> allGroupings() {
return allGroupings;
}
+ /**
+ * Returns list all typedefs present in subtree.
+ *
+ * @return Returns list all containers present in subtree.
+ */
public List<TypeDefinition<?>> allTypedefs() {
return allTypedefs;
}
}
- private void traverseModule(DataNodeContainer dataNode) {
+ private void traverseModule(final DataNodeContainer dataNode) {
final Module module;
if (dataNode instanceof Module) {
module = (Module) dataNode;
}
}
- private void traverseGroupings(DataNodeContainer dataNode) {
+ private void traverseGroupings(final DataNodeContainer dataNode) {
final Set<GroupingDefinition> groupings = dataNode.getGroupings();
if (groupings != null) {
for (GroupingDefinition grouping : groupings) {
import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
+import com.google.common.base.Optional;
+
/**
* The <code>default</code> implementation of Decimal Type Definition interface.
*
* @see DecimalTypeDefinition
*/
public final class Decimal64 implements DecimalTypeDefinition {
- private final QName name = BaseTypes.constructQName("decimal64");
+ private static final QName NAME = BaseTypes.DECIMAL64_QNAME;
private final SchemaPath path;
private static final String UNITS = "";
private static final BigDecimal DEFAULT_VALUE = null;
*
* @see DecimalTypeDefinition
* @exception IllegalArgumentException
+ * @deprecated Use static factory {@link #create(SchemaPath, Integer)}.
*/
+ @Deprecated
public Decimal64(final SchemaPath path, final Integer fractionDigits) {
if (!((fractionDigits.intValue() >= 1) && (fractionDigits.intValue() <= MAX_NUMBER_OF_FRACTION_DIGITS))) {
throw new IllegalArgumentException(
this.path = path;
}
+ public static Decimal64 create(final SchemaPath path, final Integer fractionDigits) {
+ return new Decimal64(path, fractionDigits);
+ }
+
/**
* Returns unmodifiable List with default definition of Range Statements.
*
final BigDecimal min = new BigDecimal("-922337203685477580.8");
final BigDecimal max = new BigDecimal("922337203685477580.7");
final String rangeDescription = "Integer values between " + min + " and " + max + ", inclusively.";
- rangeStmts.add(BaseConstraints.rangeConstraint(min, max, rangeDescription,
- "https://tools.ietf.org/html/rfc6020#section-9.2.4"));
+ rangeStmts.add(BaseConstraints.newRangeConstraint(min, max, Optional.of(rangeDescription),
+ Optional.of("https://tools.ietf.org/html/rfc6020#section-9.2.4")));
return Collections.unmodifiableList(rangeStmts);
}
@Override
public QName getQName() {
- return name;
+ return NAME;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((NAME == null) ? 0 : NAME.hashCode());
result = prime * result + ((path == null) ? 0 : path.hashCode());
return result;
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
return false;
}
Decimal64 other = (Decimal64) obj;
- if (name == null) {
- if (other.name != null) {
- return false;
- }
- } else if (!name.equals(other.name)) {
- return false;
- }
if (path == null) {
if (other.path != null) {
return false;
@Override
public String toString() {
- return Decimal64.class.getSimpleName() + "[qname=" + name + ", fractionDigits=" + fractionDigits + "]";
+ return Decimal64.class.getSimpleName() + "[qname=" + NAME + ", fractionDigits=" + fractionDigits + "]";
}
}
import java.util.Collections;
import java.util.List;
+import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.Status;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
-public final class EmptyType implements EmptyTypeDefinition {
- private static EmptyType instance;
- private static final QName NAME = BaseTypes.constructQName("empty");
+public final class EmptyType implements EmptyTypeDefinition, Immutable {
+ private static final EmptyType INSTANCE = new EmptyType();
+ private static final QName NAME = BaseTypes.EMPTY_QNAME;
private static final SchemaPath PATH = SchemaPath.create(Collections.singletonList(NAME), true);
private static final String DESCRIPTION = "The empty built-in type represents a leaf that does not have any value, it conveys information by its presence or absence.";
private static final String REFERENCE = "https://tools.ietf.org/html/rfc6020#page-131";
}
public static EmptyType getInstance() {
- if (instance == null) {
- instance = new EmptyType();
- }
- return instance;
+ return INSTANCE;
}
@Override
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
/**
private final EnumPair defaultEnum;
private final List<EnumPair> enums;
+
+ /**
+ * Constructs EnumerationType
+ *
+ * @param path
+ * @param enums
+ * @deprecated Use {@link #create(SchemaPath, List, Optional)} instead.
+ */
+ @Deprecated
public EnumerationType(final SchemaPath path, final List<EnumPair> enums) {
- super();
- this.path = path;
- this.enums = ImmutableList.copyOf(enums);
- this.defaultEnum = null;
+ this(path,enums,Optional.<EnumPair>absent());
}
+ /**
+ * Constructs EnumerationType
+ *
+ * @param path
+ * @param defaultEnum
+ * @param enums
+ * @deprecated Use {@link #create(SchemaPath, List, Optional)} instead.
+ */
+ @Deprecated
public EnumerationType(final SchemaPath path, final EnumPair defaultEnum, final List<EnumPair> enums) {
- super();
- this.path = path;
- this.defaultEnum = defaultEnum;
- this.enums = ImmutableList.copyOf(enums);
+ this(path,enums,Optional.fromNullable(defaultEnum));
+ }
+
+ private EnumerationType(final SchemaPath path, final List<EnumPair> enums, final Optional<EnumPair> defaultEnum) {
+ this.path = Preconditions.checkNotNull(path,"path must not be null");
+ this.enums = ImmutableList.copyOf(Preconditions.checkNotNull(enums, "enums must not be null."));
+ if(defaultEnum.isPresent()) {
+ Preconditions.checkArgument(enums.contains(defaultEnum.get()),"defaultEnum must be contained in defined enumerations.");
+ this.defaultEnum = defaultEnum.get();
+ } else {
+ this.defaultEnum = null;
+ }
+ }
+
+ /**
+ *
+ * Constructs new enumeration
+ *
+ * @param path Schema Path to definition point of this enumeration
+ * @param enums List of defined enumeration values
+ * @param defaultValue {@link Optional#of(Object)} of default value, {@link Optional#absent()} if no default value is defined.
+ * If defaultValue is set, it must be present in provided list of enumerations.
+ *
+ */
+ public static EnumerationType create(final SchemaPath path, final List<EnumPair> enums, final Optional<EnumPair> defaultValue) {
+ return new EnumerationType(path, enums, defaultValue);
}
/*
import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+/**
+ * Extended Type represents YANG type derived from other type.
+ *
+ * Extended type object is decorator on top of existing {@link TypeDefinition}
+ * which represents original type, and extended type
+ * may define additional constraints, modify description or reference
+ * of parent type or provide new type capture for specific use-cases.
+ *
+ */
public class ExtendedType implements TypeDefinition<TypeDefinition<?>> {
private final QName typeName;
private List<PatternConstraint> patterns = Collections.emptyList();
private Integer fractionDigits = null;
- private Status status;
- private String units;
- private Object defaultValue;
- private boolean addedByUses;
+ private final Status status;
+ private final String units;
+ private final Object defaultValue;
+ private final boolean addedByUses;
+
+ /**
+ *
+ * Creates Builder for extended / derived type.
+ *
+ * @param typeName QName of derived type
+ * @param baseType Base type of derived type
+ * @param description Description of type
+ * @param reference Reference of Type
+ * @param path Schema path to type definition.
+ */
+ public static final Builder builder(final QName typeName,final TypeDefinition<?> baseType,final Optional<String> description,final Optional<String> reference,final SchemaPath path) {
+ return new Builder(typeName, baseType, description.or(""), reference.or(""), path);
+ }
public static class Builder {
private final QName typeName;
private List<PatternConstraint> patterns = Collections.emptyList();
private Integer fractionDigits = null;
+ /**
+ *
+ * @param actualPath
+ * @param namespace
+ * @param revision
+ * @param typeName
+ * @param baseType
+ * @param description
+ * @param reference
+ *
+ * @deprecated Use {@link ExtendedType#builder(QName, TypeDefinition, Optional, Optional, SchemaPath)} instead.
+ */
+ @Deprecated
public Builder(final List<String> actualPath, final URI namespace,
final Date revision, final QName typeName,
- TypeDefinition<?> baseType, final String description,
+ final TypeDefinition<?> baseType, final String description,
final String reference) {
- this.typeName = typeName;
- this.baseType = baseType;
- this.path = BaseTypes.schemaPath(actualPath, namespace, revision);
- this.description = description;
- this.reference = reference;
+ this(typeName,baseType,description,reference,BaseTypes.schemaPath(actualPath, namespace, revision));
}
- public Builder(final QName typeName, TypeDefinition<?> baseType,
+ /**
+ *
+ * Creates Builder for extended / derived type.
+ *
+ * @param typeName QName of derived type
+ * @param baseType Base type of derived type
+ * @param description Description of type
+ * @param reference Reference of Type
+ * @param path Schema path to type definition.
+ *
+ * @deprecated Use {@link ExtendedType#builder(QName, TypeDefinition, Optional, Optional, SchemaPath)} instead.
+ */
+ @Deprecated
+ public Builder(final QName typeName, final TypeDefinition<?> baseType,
final String description, final String reference,
- SchemaPath path) {
- this.typeName = typeName;
- this.baseType = baseType;
- this.path = path;
+ final SchemaPath path) {
+ this.typeName = Preconditions.checkNotNull(typeName, "type name must not be null.");
+ this.baseType = Preconditions.checkNotNull(baseType, "base type must not be null");
+ this.path = Preconditions.checkNotNull(path, "path must not be null.");
this.description = description;
this.reference = reference;
}
- public Builder status(Status status) {
+ public Builder status(final Status status) {
this.status = status;
return this;
}
- public Builder units(String units) {
+ public Builder units(final String units) {
this.units = units;
return this;
}
}
}
- private ExtendedType(Builder builder) {
+ private ExtendedType(final Builder builder) {
this.typeName = builder.typeName;
this.baseType = builder.baseType;
this.path = builder.path;
}
@Override
- public boolean equals(Object o) {
+ public boolean equals(final Object o) {
if (this == o) {
return true;
}
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import com.google.common.base.Preconditions;
+
/**
* The <code>default</code> implementation of Identityref Type Definition
* interface.
* @see IdentityrefTypeDefinition
*/
public final class IdentityrefType implements IdentityrefTypeDefinition {
- private final QName name = BaseTypes.constructQName("identityref");
+ private static final QName NAME = BaseTypes.IDENTITYREF_QNAME;
private final SchemaPath path;
private static final String DESCRIPTION = "The identityref type is used to reference an existing identity.";
private static final String REFERENCE = "https://tools.ietf.org/html/rfc6020#section-9.10";
private final IdentitySchemaNode identity;
private static final String UNITS = "";
- public IdentityrefType(IdentitySchemaNode identity, SchemaPath schemaPath) {
- this.identity = identity;
- this.path = schemaPath;
+ /**
+ * Constructs new {@link IdentityrefTypeDefinition} definition.
+ *
+ * @param identity
+ * @param schemaPath
+ */
+ @Deprecated
+ public IdentityrefType(final IdentitySchemaNode identity, final SchemaPath schemaPath) {
+ this(schemaPath,identity);
+ }
+
+ private IdentityrefType(final SchemaPath path, final IdentitySchemaNode baseIdentity) {
+ this.path = Preconditions.checkNotNull(path, "Path must be specified");
+ this.identity = Preconditions.checkNotNull(baseIdentity,"baseIdentity must be specified.");
+ }
+
+ /**
+ *
+ * Constructs new {@link IdentityrefTypeDefinition} definition.
+ *
+ * @param path Path to the definition.
+ * @param baseIdentity Base Identity, all derived identities are valid arguments for instance of this type.
+ * @return New identityref definition.
+ */
+ public static IdentityrefType create(final SchemaPath path, final IdentitySchemaNode baseIdentity) {
+ return new IdentityrefType(path, baseIdentity);
}
@Override
@Override
public QName getQName() {
- return name;
+ return NAME;
}
@Override
import java.util.Collections;
import java.util.List;
+import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
* The <code>default</code> implementation of Instance Identifier Type
* Definition interface.
*
+ * Instance Identifier has only two possible variants - one with
+ * {@link #requireInstance()} which returns true, other one
+ * returns false.
+ *
* @see InstanceIdentifierTypeDefinition
- * @deprecated Depracated, use {@link org.opendaylight.yangtools.yang.data.api.InstanceIdentifier} instead
+ *
*/
-@Deprecated
-public final class InstanceIdentifier implements InstanceIdentifierTypeDefinition {
- private static final QName NAME = BaseTypes.constructQName("instance-identifier");
- private static final SchemaPath PATH = new SchemaPath(Collections.singletonList(NAME), true);
+public final class InstanceIdentifier implements InstanceIdentifierTypeDefinition, Immutable {
+
+ private static final QName NAME = BaseTypes.INSTANCE_IDENTIFIER_QNAME;
+ private static final SchemaPath PATH = SchemaPath.create(Collections.singletonList(NAME), true);
private static final String DESCRIPTION = "The instance-identifier built-in type is used to "
+ "uniquely identify a particular instance node in the data tree.";
private static final String REFERENCE = "https://tools.ietf.org/html/rfc6020#section-9.13";
- private final RevisionAwareXPath xpath;
private static final String UNITS = "";
- private boolean requireInstance = true;
+ private final Boolean requireInstance;
- private static final int HASH_BOOLEAN_TRUE = 1231;
- private static final int HASH_BOOLEAN_FALSE = 1237;
+ private static final InstanceIdentifier INSTANCE_WITH_REQUIRED_TRUE = new InstanceIdentifier(true);
+ private static final InstanceIdentifier INSTANCE_WITH_REQUIRED_FALSE = new InstanceIdentifier(false);
+ /**
+ * Constructs new instance identifier.
+ *
+ * @param xpath
+ * @deprecated Use {@link #getInstance()} for default one, since Instance Identifier does not have xpath.
+ */
+ @Deprecated
public InstanceIdentifier(final RevisionAwareXPath xpath) {
- this.xpath = xpath;
+ requireInstance = true;
}
+ /**
+ * Constructs new instance identifier.
+ *
+ * @param xpath
+ * @param requireInstance if instance of data is required
+ * @deprecated Use {@link #create(boolean)}, since Instance Identifier does not have xpath.
+ */
+ @Deprecated
public InstanceIdentifier(final RevisionAwareXPath xpath, final boolean requireInstance) {
- this.xpath = xpath;
this.requireInstance = requireInstance;
}
+ private InstanceIdentifier(final boolean requiredInstance) {
+ this.requireInstance = requiredInstance;
+ }
+
+ public static InstanceIdentifier getInstance() {
+ return INSTANCE_WITH_REQUIRED_TRUE;
+ }
+
+ public static InstanceIdentifier create(final boolean requireInstance) {
+ return requireInstance ? INSTANCE_WITH_REQUIRED_TRUE : INSTANCE_WITH_REQUIRED_FALSE;
+ }
+
/*
* (non-Javadoc)
*
*/
@Override
public Object getDefaultValue() {
- return xpath;
+ return null;
}
/*
* InstanceIdentifierTypeDefinition# getPathStatement()
*/
@Override
+ @Deprecated
public RevisionAwareXPath getPathStatement() {
- return xpath;
+ return null;
}
/*
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + (requireInstance ? HASH_BOOLEAN_TRUE : HASH_BOOLEAN_FALSE);
- result = prime * result + ((xpath == null) ? 0 : xpath.hashCode());
+ result = prime * result + requireInstance.hashCode();
return result;
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
return false;
}
InstanceIdentifier other = (InstanceIdentifier) obj;
- if (requireInstance != other.requireInstance) {
- return false;
- }
- if (xpath == null) {
- if (other.xpath != null) {
- return false;
- }
- } else if (!xpath.equals(other.xpath)) {
- return false;
- }
- return true;
+ return requireInstance.equals(other.requireInstance);
}
+
+
}
*/
package org.opendaylight.yangtools.yang.model.util;
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.concepts.Immutable;
/**
* Implementation of Yang int16 built-in type. <br>
*
* @see AbstractSignedInteger
*/
-public final class Int16 extends AbstractSignedInteger {
- private static Int16 instance;
- private static final QName NAME = BaseTypes.constructQName("int16");
+public final class Int16 extends AbstractSignedInteger implements Immutable {
private static final String DESCRIPTION = "int16 represents integer values between -32768 and 32767, inclusively.";
+ private static final Int16 INSTANCE = new Int16();
+
private Int16() {
- super(NAME, DESCRIPTION, Short.MIN_VALUE, Short.MAX_VALUE, "");
+ super(BaseTypes.INT16_QNAME, DESCRIPTION, Short.MIN_VALUE, Short.MAX_VALUE, "");
}
+ /**
+ * Returns default instance of int16 type.
+ * @return default instance of int16 type.
+ */
public static Int16 getInstance() {
- if (instance == null) {
- instance = new Int16();
- }
- return instance;
+ return INSTANCE;
}
@Override
@Override
public String toString() {
- return "type " + NAME;
+ return "type " + BaseTypes.INT16_QNAME;
}
}
*/
package org.opendaylight.yangtools.yang.model.util;
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.concepts.Immutable;
/**
* Implementation of Yang int32 built-in type. <br>
* @see AbstractSignedInteger
*
*/
-public final class Int32 extends AbstractSignedInteger {
- private static Int32 instance;
- private static final QName NAME = BaseTypes.constructQName("int32");
+public final class Int32 extends AbstractSignedInteger implements Immutable {
private static final String DESCRIPTION = "int32 represents integer values between -2147483648 and 2147483647, inclusively.";
+
+ private static final Int32 INSTANCE = new Int32();
+
private Int32() {
- super(Int32.NAME, Int32.DESCRIPTION, Integer.MIN_VALUE, Integer.MAX_VALUE, "");
+ super(BaseTypes.INT32_QNAME, Int32.DESCRIPTION, Integer.MIN_VALUE, Integer.MAX_VALUE, "");
}
+ /**
+ * Returns default instance of int32 type.
+ * @return default instance of int32 type.
+ */
public static Int32 getInstance() {
- if (instance == null) {
- instance = new Int32();
- }
- return instance;
+ return INSTANCE;
}
@Override
@Override
public String toString() {
- return "type " + NAME;
+ return "type " + BaseTypes.INT32_QNAME;
}
+
}
*/
package org.opendaylight.yangtools.yang.model.util;
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.concepts.Immutable;
/**
* Implementation of Yang int64 built-in type. <br>
* type is {@link Long}.
*
*/
-public final class Int64 extends AbstractSignedInteger {
- private static Int64 instance;
- private static final QName NAME = BaseTypes.constructQName("int64");
+public final class Int64 extends AbstractSignedInteger implements Immutable {
private static final String DESCRIPTION = "int64 represents integer values between -9223372036854775808 and 9223372036854775807, inclusively.";
private Int64() {
- super(NAME, DESCRIPTION, Long.MIN_VALUE, Long.MAX_VALUE, "");
+ super(BaseTypes.INT64_QNAME, DESCRIPTION, Long.MIN_VALUE, Long.MAX_VALUE, "");
}
+
+ private static final Int64 INSTANCE = new Int64();
+
+ /**
+ * Returns default instance of int64 type.
+ * @return default instance of int64 type.
+ */
public static Int64 getInstance() {
- if (instance == null) {
- instance = new Int64();
- }
- return instance;
+ return INSTANCE;
}
@Override
@Override
public String toString() {
- return "type " + NAME;
+ return "type " + BaseTypes.INT64_QNAME;
}
-
}
*/
package org.opendaylight.yangtools.yang.model.util;
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.concepts.Immutable;
/**
* Implementation of Yang int8 built-in type. <br>
*
* @see AbstractSignedInteger
*/
-public final class Int8 extends AbstractSignedInteger {
- private static Int8 instance;
- private static final QName NAME = BaseTypes.constructQName("int8");
+public final class Int8 extends AbstractSignedInteger implements Immutable {
private static final String DESCRIPTION = "represents integer values between -128 and 127, inclusively.";
private Int8() {
- super(NAME, DESCRIPTION, Byte.MIN_VALUE, Byte.MAX_VALUE, "");
+ super(BaseTypes.INT8_QNAME, DESCRIPTION, Byte.MIN_VALUE, Byte.MAX_VALUE, "");
}
+ private static final Int8 INSTANCE = new Int8();
+
+ /**
+ * Returns default instance of int8 type.
+ * @return default instance of int8 type.
+ */
public static Int8 getInstance() {
- if (instance == null) {
- instance = new Int8();
- }
- return instance;
+ return INSTANCE;
}
@Override
@Override
public String toString() {
- return "type " + NAME;
+ return "type " + BaseTypes.INT8_QNAME;
}
}
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
+import com.google.common.base.Preconditions;
+
/**
* The <code>default</code> implementation of Instance Leafref Type Definition
* interface.
private static final String REF = "https://tools.ietf.org/html/rfc6020#section-9.9";
private final RevisionAwareXPath xpath;
+ private final SchemaPath path;
+ @Deprecated
public Leafref(final RevisionAwareXPath xpath) {
- this.xpath = xpath;
+ this(PATH,xpath);
+
+ }
+
+ private Leafref(final SchemaPath path, final RevisionAwareXPath target) {
+ this.path = Preconditions.checkNotNull(path,"path must be specified");
+ this.xpath = Preconditions.checkNotNull(target,"target must not be null.");
+ }
+
+ public static Leafref create(final SchemaPath path,final RevisionAwareXPath target) {
+ return new Leafref(path,target);
}
@Override
@Override
public SchemaPath getPath() {
- return PATH;
+ return path;
}
@Override
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.model.util;
+
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ * {@link Immutable} implementation of {@link LengthConstraint}.
+ *
+ * Length constraint based on supplied parameters with additional behaviour:
+ *
+ * <ul>
+ * <li>{@link LengthConstraint#getErrorAppTag()} returns
+ * <code>length-out-of-specified-bounds</code>
+ * <li>{@link LengthConstraint#getErrorMessage() returns <code>The argument is
+ * out of bounds <<i>min</i>, <i>max</i> ></code>
+ * </ul
+ */
+final class LengthConstraintImpl implements LengthConstraint, Immutable {
+
+ private final Number min;
+ private final Number max;
+
+ private final String description;
+ private final String reference;
+
+ private final String errorAppTag;
+ private final String errorMessage;
+
+ LengthConstraintImpl(final Number min, final Number max, final Optional<String> description,
+ final Optional<String> reference) {
+ super();
+ this.min = Preconditions.checkNotNull(min, "min must not be null.");
+ this.max = Preconditions.checkNotNull(max, "max must not be null");
+ this.description = description.orNull();
+ this.reference = reference.orNull();
+
+ this.errorAppTag = "length-out-of-specified-bounds";
+ this.errorMessage = "The argument is out of bounds <" + min + ", " + max + ">";
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String getErrorAppTag() {
+ return errorAppTag;
+ }
+
+ @Override
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ @Override
+ public Number getMin() {
+ return min;
+ }
+
+ @Override
+ public Number getMax() {
+ return max;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((description == null) ? 0 : description.hashCode());
+ result = prime * result + errorAppTag.hashCode();
+ result = prime * result + errorMessage.hashCode();
+ result = prime * result + max.hashCode();
+ result = prime * result + min.hashCode();
+ result = prime * result + ((reference == null) ? 0 : reference.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final LengthConstraintImpl other = (LengthConstraintImpl) obj;
+ if (description == null) {
+ if (other.description != null) {
+ return false;
+ }
+ } else if (!description.equals(other.description)) {
+ return false;
+ }
+ if (errorAppTag == null) {
+ if (other.errorAppTag != null) {
+ return false;
+ }
+ } else if (!errorAppTag.equals(other.errorAppTag)) {
+ return false;
+ }
+ if (errorMessage == null) {
+ if (other.errorMessage != null) {
+ return false;
+ }
+ } else if (!errorMessage.equals(other.errorMessage)) {
+ return false;
+ }
+ if (max != other.max) {
+ return false;
+ }
+ if (min != other.min) {
+ return false;
+ }
+ if (reference == null) {
+ if (other.reference != null) {
+ return false;
+ }
+ } else if (!reference.equals(other.reference)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("LengthConstraintImpl [min=");
+ builder.append(min);
+ builder.append(", max=");
+ builder.append(max);
+ builder.append(", description=");
+ builder.append(description);
+ builder.append(", errorAppTag=");
+ builder.append(errorAppTag);
+ builder.append(", reference=");
+ builder.append(reference);
+ builder.append(", errorMessage=");
+ builder.append(errorMessage);
+ builder.append("]");
+ return builder.toString();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2014 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.model.util;
+
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ * {@link Immutable} implementation of {@link PatternConstraint}
+ *
+ * Creates an instance of Range constraint based on supplied parameters with
+ * additional behaviour:
+ *
+ * <ul>
+ * <li>{@link PatternConstraint#getErrorAppTag()} returns
+ * <code>invalid-regular-expression</code>
+ * </ul>
+ *
+ */
+final class PatternConstraintImpl implements PatternConstraint, Immutable {
+
+ private final String regex;
+ private final String description;
+ private final String reference;
+
+ private final String errorAppTag;
+ private final String errorMessage;
+
+ public PatternConstraintImpl(final String regex, final Optional<String> description,
+ final Optional<String> reference) {
+ super();
+ this.regex = Preconditions.checkNotNull(regex, "regex must not be null.");
+ this.description = description.orNull();
+ this.reference = reference.orNull();
+
+ // FIXME: Lookup better suitable error tag.
+ errorAppTag = "invalid-regular-expression";
+ // TODO: add erro message
+ errorMessage = "";
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String getErrorAppTag() {
+ return errorAppTag;
+ }
+
+ @Override
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ @Override
+ public String getRegularExpression() {
+ return regex;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((description == null) ? 0 : description.hashCode());
+ result = prime * result + ((errorAppTag == null) ? 0 : errorAppTag.hashCode());
+ result = prime * result + ((errorMessage == null) ? 0 : errorMessage.hashCode());
+ result = prime * result + ((reference == null) ? 0 : reference.hashCode());
+ result = prime * result + regex.hashCode();
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final PatternConstraintImpl other = (PatternConstraintImpl) obj;
+ if (description == null) {
+ if (other.description != null) {
+ return false;
+ }
+ } else if (!description.equals(other.description)) {
+ return false;
+ }
+ if (errorAppTag == null) {
+ if (other.errorAppTag != null) {
+ return false;
+ }
+ } else if (!errorAppTag.equals(other.errorAppTag)) {
+ return false;
+ }
+ if (errorMessage == null) {
+ if (other.errorMessage != null) {
+ return false;
+ }
+ } else if (!errorMessage.equals(other.errorMessage)) {
+ return false;
+ }
+ if (reference == null) {
+ if (other.reference != null) {
+ return false;
+ }
+ } else if (!reference.equals(other.reference)) {
+ return false;
+ }
+ if (regex == null) {
+ if (other.regex != null) {
+ return false;
+ }
+ } else if (!regex.equals(other.regex)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("PatternConstraintImpl [regex=");
+ builder.append(regex);
+ builder.append(", description=");
+ builder.append(description);
+ builder.append(", reference=");
+ builder.append(reference);
+ builder.append(", errorAppTag=");
+ builder.append(errorAppTag);
+ builder.append(", errorMessage=");
+ builder.append(errorMessage);
+ builder.append("]");
+ return builder.toString();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2014 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.model.util;
+
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
+import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ * {@link Immutable} implementation of {@link LengthConstraint}.
+ *
+ * Range constraint based on supplied parameters with additional behaviour:
+ *
+ * <ul>
+ * <li>{@link RangeConstraint#getErrorAppTag()} returns
+ * <code>range-out-of-specified-bounds</code>
+ * <li>{@link RangeConstraint#getErrorMessage() returns <code>The argument is
+ * out of bounds <<i>min</i>, <i>max</i> ></code>
+ * </ul>
+ */
+final class RangeConstraintImpl implements RangeConstraint, Immutable {
+ private final Number min;
+ private final Number max;
+
+ private final String description;
+ private final String reference;
+
+ private final String errorAppTag;
+ private final String errorMessage;
+
+ RangeConstraintImpl(final Number min, final Number max, final Optional<String> description,
+ final Optional<String> reference) {
+ super();
+ this.min = Preconditions.checkNotNull(min, "min must not be null.");
+ this.max = Preconditions.checkNotNull(max, "max must not be null.");
+ this.description = description.orNull();
+ this.reference = reference.orNull();
+
+ this.errorAppTag = "range-out-of-specified-bounds";
+ this.errorMessage = "The argument is out of bounds <" + min + ", " + max + ">";
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String getErrorAppTag() {
+ return errorAppTag;
+ }
+
+ @Override
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ @Override
+ public Number getMin() {
+ return min;
+ }
+
+ @Override
+ public Number getMax() {
+ return max;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((description == null) ? 0 : description.hashCode());
+ result = prime * result + errorAppTag.hashCode();
+ result = prime * result + errorMessage.hashCode();
+ result = prime * result + max.hashCode();
+ result = prime * result + min.hashCode();
+ result = prime * result + ((reference == null) ? 0 : reference.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final RangeConstraintImpl other = (RangeConstraintImpl) obj;
+ if (description == null) {
+ if (other.description != null) {
+ return false;
+ }
+ } else if (!description.equals(other.description)) {
+ return false;
+ }
+ if (max == null) {
+ if (other.max != null) {
+ return false;
+ }
+ } else if (!max.equals(other.max)) {
+ return false;
+ }
+ if (min == null) {
+ if (other.min != null) {
+ return false;
+ }
+ } else if (!min.equals(other.min)) {
+ return false;
+ }
+ if (reference == null) {
+ if (other.reference != null) {
+ return false;
+ }
+ } else if (!reference.equals(other.reference)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("RangeConstraintImpl [min=");
+ builder.append(min);
+ builder.append(", max=");
+ builder.append(max);
+ builder.append(", description=");
+ builder.append(description);
+ builder.append(", reference=");
+ builder.append(reference);
+ builder.append(", errorAppTag=");
+ builder.append(errorAppTag);
+ builder.append(", errorMessage=");
+ builder.append(errorMessage);
+ builder.append("]");
+ return builder.toString();
+ }
+}
\ No newline at end of file
import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
/**
- * The <code>default</code> implementation of Instance Rewision Aware XPath
+ * The <code>helper</code> implementation of Instance Rewision Aware XPath
* interface.
- *
+ *
* @see RevisionAwareXPath
*/
public class RevisionAwareXPathImpl implements RevisionAwareXPath {
private static final int HASH_BOOLEAN_TRUE = 1231;
private static final int HASH_BOOLEAN_FALSE = 1237;
- public RevisionAwareXPathImpl(String xpath, boolean absolute) {
+ public RevisionAwareXPathImpl(final String xpath, final boolean absolute) {
this.xpath = xpath;
this.absolute = absolute;
}
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
*/
package org.opendaylight.yangtools.yang.model.util;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.api.Status;
import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
+import com.google.common.base.Optional;
+
/**
* The <code>default</code> implementation of String Type Definition interface.
*
* @see StringTypeDefinition
*/
-public final class StringType implements StringTypeDefinition {
- private static final StringType INSTANCE = new StringType();
- private final QName name = BaseTypes.constructQName("string");
- private final SchemaPath path = SchemaPath.create(Collections.singletonList(name), true);
+public final class StringType implements StringTypeDefinition, Immutable {
+ private static final QName NAME = BaseTypes.STRING_QNAME;
+ private static final SchemaPath PATH = SchemaPath.create(Collections.singletonList(NAME), true);
private static final String DEFAULT_VALUE = "";
private static final String DESCRIPTION = "";
private static final String REFERENCE = "";
private final List<PatternConstraint> patterns;
private static final String UNITS = "";
+ private static final StringType INSTANCE = new StringType();
+
/**
* Default Constructor.
*/
private StringType() {
- final List<LengthConstraint> constraints = new ArrayList<LengthConstraint>();
- constraints.add(BaseConstraints.lengthConstraint(0, Integer.MAX_VALUE, "", ""));
- lengthStatements = Collections.unmodifiableList(constraints);
+ lengthStatements = Collections.singletonList(BaseConstraints.newLengthConstraint(0, Integer.MAX_VALUE, Optional.of(""), Optional.of("")));
patterns = Collections.emptyList();
}
*/
@Override
public QName getQName() {
- return name;
+ return NAME;
}
/*
*/
@Override
public SchemaPath getPath() {
- return path;
+ return PATH;
}
/*
final int prime = 31;
int result = 1;
result = prime * result + ((lengthStatements == null) ? 0 : lengthStatements.hashCode());
- result = prime * result + ((name == null) ? 0 : name.hashCode());
- result = prime * result + ((path == null) ? 0 : path.hashCode());
+ result = prime * result + NAME.hashCode();
+ result = prime * result + PATH.hashCode();
result = prime * result + ((patterns == null) ? 0 : patterns.hashCode());
return result;
}
} else if (!lengthStatements.equals(other.lengthStatements)) {
return false;
}
- if (name == null) {
- if (other.name != null) {
- return false;
- }
- } else if (!name.equals(other.name)) {
- return false;
- }
- if (path == null) {
- if (other.path != null) {
- return false;
- }
- } else if (!path.getPath().equals(other.path.getPath())) {
- return false;
- }
if (patterns == null) {
if (other.patterns != null) {
return false;
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("StringType [name=");
- builder.append(name);
+ builder.append(NAME);
builder.append(", path=");
- builder.append(path);
+ builder.append(PATH);
builder.append(", defaultValue=");
builder.append(DEFAULT_VALUE);
builder.append(", description=");
*/
package org.opendaylight.yangtools.yang.model.util;
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.concepts.Immutable;
/**
* Implementation of Yang uint16 built-in type. <br>
* counterpart of Yang uint16 built-in type is {@link Integer}.
*
*/
-public final class Uint16 extends AbstractUnsignedInteger {
+public final class Uint16 extends AbstractUnsignedInteger implements Immutable {
public static final int MAX_VALUE = 65535;
- private static Uint16 instance;
- private static final QName NAME = BaseTypes.constructQName("uint16");
private static final String DESCRIPTION = "uint16 represents integer values between 0 and 65535, inclusively.";
+ private static Uint16 INSTANCE = new Uint16();
+
private Uint16() {
- super(NAME, DESCRIPTION, MAX_VALUE, "");
+ super(BaseTypes.UINT16_QNAME, DESCRIPTION, MAX_VALUE, "");
}
public static Uint16 getInstance() {
- if (instance == null) {
- instance = new Uint16();
- }
- return instance;
+ return INSTANCE;
}
@Override
@Override
public String toString() {
- return "type " + NAME;
+ return "type " + BaseTypes.UINT16_QNAME;
}
}
*/
package org.opendaylight.yangtools.yang.model.util;
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.concepts.Immutable;
/**
* Implementation of Yang uint32 built-in type. <br>
* uint32 represents integer values between 0 and 4294967295, inclusively.
*
*/
-public final class Uint32 extends AbstractUnsignedInteger {
+public final class Uint32 extends AbstractUnsignedInteger implements Immutable {
public static final long MAX_VALUE = 4294967295L;
- private static Uint32 instance;
- private static final QName NAME = BaseTypes.constructQName("uint32");
private static final String DESCRIPTION = "uint32 represents integer values between 0 and 4294967295, inclusively.";
+ private static final Uint32 INSTANCE = new Uint32();
+
+
private Uint32() {
- super(NAME, DESCRIPTION, MAX_VALUE, "");
+ super(BaseTypes.UINT32_QNAME, DESCRIPTION, MAX_VALUE, "");
}
public static Uint32 getInstance() {
- if (instance == null) {
- instance = new Uint32();
- }
- return instance;
+ return INSTANCE;
}
@Override
@Override
public String toString() {
- return "type " + NAME;
+ return "type " + BaseTypes.UINT32_QNAME;
}
}
import java.math.BigInteger;
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.concepts.Immutable;
/**
* Implementation of Yang uint64 built-in type. <br>
* {@link BigInteger}.
*
*/
-public final class Uint64 extends AbstractUnsignedInteger {
+public final class Uint64 extends AbstractUnsignedInteger implements Immutable {
public static final BigInteger MAX_VALUE = new BigInteger("18446744073709551615");
- private static Uint64 instance;
- private static final QName NAME = BaseTypes.constructQName("uint64");
private static final String DESCRIPTION = "uint64 represents integer values between 0 and 18446744073709551615, inclusively.";
+ private static final Uint64 INSTANCE = new Uint64();
+
private Uint64() {
- super(NAME, DESCRIPTION, MAX_VALUE, "");
+ super(BaseTypes.UINT64_QNAME, DESCRIPTION, MAX_VALUE, "");
}
public static Uint64 getInstance() {
- if (instance == null) {
- instance = new Uint64();
- }
- return instance;
+ return INSTANCE;
}
@Override
@Override
public String toString() {
- return "type " + NAME;
+ return "type " + BaseTypes.UINT64_QNAME;
}
}
*/
package org.opendaylight.yangtools.yang.model.util;
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.concepts.Immutable;
/**
* Implementation of Yang uint8 built-in type. <br>
*
* @see AbstractUnsignedInteger
*/
-public final class Uint8 extends AbstractUnsignedInteger {
+public final class Uint8 extends AbstractUnsignedInteger implements Immutable {
public static final int MAX_VALUE = 255;
- private static Uint8 instance;
- private static final QName NAME = BaseTypes.constructQName("uint8");
private static final String DESCRIPTION = "uint8 represents integer values between 0 and 255, inclusively.";
+ private static final Uint8 INSTANCE = new Uint8();
+
private Uint8() {
- super(NAME, DESCRIPTION, MAX_VALUE, "");
+ super(BaseTypes.UINT8_QNAME, DESCRIPTION, MAX_VALUE, "");
}
public static Uint8 getInstance() {
- if (instance == null) {
- instance = new Uint8();
- }
- return instance;
+ return INSTANCE;
}
@Override
@Override
public String toString() {
- return "type " + NAME;
+ return "type " + BaseTypes.UINT8_QNAME;
}
}
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
public final class UnionType implements UnionTypeDefinition {
- private final QName name = BaseTypes.constructQName("union");
- private final SchemaPath path = BaseTypes.schemaPath(name);
+ private final SchemaPath path = SchemaPath.create(Collections.singletonList(BaseTypes.UNION_QNAME),true);
private static final String DESCRIPTION = "The union built-in type represents a value that corresponds to one of its member types.";
private static final String REFERENCE = "https://tools.ietf.org/html/rfc6020#section-9.12";
private final List<TypeDefinition<?>> types;
- public UnionType(List<TypeDefinition<?>> types) {
- if (types == null) {
- throw new IllegalArgumentException("When the type is 'union', the 'type' statement MUST be present.");
- }
- this.types = types;
+ @Deprecated
+ public UnionType(final List<TypeDefinition<?>> types) {
+ Preconditions.checkNotNull(types,"When the type is 'union', the 'type' statement MUST be present.");
+ this.types = ImmutableList.copyOf(types);
+ }
+
+ public static UnionType create(final List<TypeDefinition<?>> types) {
+ return new UnionType(types);
}
@Override
@Override
public QName getQName() {
- return name;
+ return BaseTypes.UNION_QNAME;
}
@Override
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("type ");
- builder.append(name);
+ builder.append(BaseTypes.UNION_QNAME);
builder.append(" (types=[");
for (TypeDefinition<?> td : types) {
builder.append(", " + td.getQName().getLocalName());
import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
import org.opendaylight.yangtools.yang.model.api.type.UnknownTypeDefinition;
+/**
+ * Utility implementation of unknown type definition.
+ *
+ * Unknown type definition is derived type, for
+ * which base built-in type is not yet known. This types
+ * are possible during parsing and resolving of YANG model
+ * without all requisites allready processed.
+ *
+ *
+ */
public final class UnknownType implements UnknownTypeDefinition {
private final QName name;
this.path = BaseTypes.schemaPath(name);
}
- public Builder description(String description) {
+ public Builder description(final String description) {
this.description = description;
return this;
}
- public Builder reference(String reference) {
+ public Builder reference(final String reference) {
this.reference = reference;
return this;
}
return this;
}
- public Builder status(Status status) {
+ public Builder status(final Status status) {
this.status = status;
return this;
}
- public Builder units(String units) {
+ public Builder units(final String units) {
this.units = units;
return this;
}
}
}
- private UnknownType(Builder builder) {
+ private UnknownType(final Builder builder) {
this.name = builder.name;
this.path = builder.path;
this.description = builder.description;
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
*/
package org.opendaylight.yangtools.yang.model.util;
-import java.util.HashSet;
-import java.util.Set;
-
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+/**
+ * Utility class which provides various helper methods for working with YANG
+ * built-in types.
+ *
+ * @deprecated Use {@link BaseTypes} instead.
+ */
+@Deprecated
public final class YangTypesConverter {
- private static final Set<String> BASE_YANG_TYPES = new HashSet<String>();
-
/**
* It isn't desirable to create the instances of this class
*/
private YangTypesConverter() {
}
- static {
- BASE_YANG_TYPES.add("binary");
- BASE_YANG_TYPES.add("bits");
- BASE_YANG_TYPES.add("boolean");
- BASE_YANG_TYPES.add("decimal64");
- BASE_YANG_TYPES.add("empty");
- BASE_YANG_TYPES.add("enumeration");
- BASE_YANG_TYPES.add("identityref");
- BASE_YANG_TYPES.add("instance-identifier");
- BASE_YANG_TYPES.add("int8");
- BASE_YANG_TYPES.add("int16");
- BASE_YANG_TYPES.add("int32");
- BASE_YANG_TYPES.add("int64");
- BASE_YANG_TYPES.add("leafref");
- BASE_YANG_TYPES.add("string");
- BASE_YANG_TYPES.add("uint8");
- BASE_YANG_TYPES.add("uint16");
- BASE_YANG_TYPES.add("uint32");
- BASE_YANG_TYPES.add("uint64");
- BASE_YANG_TYPES.add("union");
- }
-
- public static boolean isBaseYangType(String type) {
- return BASE_YANG_TYPES.contains(type);
+ @Deprecated
+ public static boolean isBaseYangType(final String type) {
+ return BaseTypes.isYangBuildInType(type);
}
- public static TypeDefinition<?> javaTypeForBaseYangType(String typeName) {
- TypeDefinition<?> type = null;
-
- if (typeName.startsWith("int")) {
- if ("int8".equals(typeName)) {
- type = Int8.getInstance();
- } else if ("int16".equals(typeName)) {
- type = Int16.getInstance();
- } else if ("int32".equals(typeName)) {
- type = Int32.getInstance();
- } else if ("int64".equals(typeName)) {
- type = Int64.getInstance();
- }
- } else if (typeName.startsWith("uint")) {
- if ("uint8".equals(typeName)) {
- type = Uint8.getInstance();
- } else if ("uint16".equals(typeName)) {
- type = Uint16.getInstance();
- } else if ("uint32".equals(typeName)) {
- type = Uint32.getInstance();
- } else if ("uint64".equals(typeName)) {
- type = Uint64.getInstance();
- }
- } else if ("string".equals(typeName)) {
- type = StringType.getInstance();
- } else if ("binary".equals(typeName)) {
- type = BinaryType.getInstance();
- } else if ("boolean".equals(typeName)) {
- type = BooleanType.getInstance();
- } else if ("empty".equals(typeName)) {
- type = EmptyType.getInstance();
- } else if ("instance-identifier".equals(typeName)) {
- // FIXME
- type = new InstanceIdentifier(null, true);
- }
-
- return type;
+ /**
+ *
+ * Returns default instance of built-in type for supplied string.
+ *
+ * @param typeName
+ * @return default instance of built-in type for supplied string or null, if
+ * default instance does not exist.
+ *
+ * @deprecated Use {@link BaseTypes#defaultBaseTypeFor(String)} instead.
+ */
+ @Deprecated
+ public static TypeDefinition<?> javaTypeForBaseYangType(final String typeName) {
+ return BaseTypes.defaultBaseTypeFor(typeName).orNull();
}
}
--- /dev/null
+/*
+ * Copyright (c) 2014 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
+ */
+/**
+ * Utility classes and implementations for concepts defined in yang-model-api.
+ *
+ *
+ * <h2>Base Types</h2>
+ *
+ * YANG specification defines several base types, for which YANG model does not
+ * exists, but have same properties as derived types. This package provides
+ * implementation of {@link org.opendaylight.yangtools.yang.model.api.TypeDefinition}
+ * interface and it's subinterfaces which represent YANG base types and
+ * types derived from them.
+ * <p>
+ * YANG Specification implicitly defines two types of base types - ones with default version,
+ * and ones which needs to be derived.
+ *
+ * <h3>Base built-in types with default instance and semantics</h3>
+ *
+ * <dl>
+ * <dt>empty</dt>
+ * <dd>A leaf that does not have any value - {@link org.opendaylight.yangtools.yang.model.util.EmptyType}</dd>
+ * <dt>binary</dt>
+ * <dd>Any binary data - {@link org.opendaylight.yangtools.yang.model.util.BinaryType}
+ * <dt>boolean</dt>
+ * <dd>"true" or "false" - {@link org.opendaylight.yangtools.yang.model.util.BinaryType}</dd>
+ * <dt>int8</dt>
+ * <dd>8-bit signed integer - {@link org.opendaylight.yangtools.yang.model.util.Int8}</dd>
+ * <dt>int16</dt>
+ * <dd>16-bit signed integer - {@link org.opendaylight.yangtools.yang.model.util.Int16}</dd>
+ * <dt>int32</dt>
+ * <dd>32-bit signed integer - {@link org.opendaylight.yangtools.yang.model.util.Int32}</dd>
+ * <dt>int64</dt>
+ * <dd>64-bit signed integer - {@link org.opendaylight.yangtools.yang.model.util.Int64}</dd>
+ * <dt>uint8</dt>
+ * <dd>8-bit unsigned integer -{@link org.opendaylight.yangtools.yang.model.util.Uint8}</dd>
+ * <dt>uint16</dt>
+ * <dd>16-bit unsigned integer - {@link org.opendaylight.yangtools.yang.model.util.Int16}</dd>
+ * <dt>uint32</dt>
+ * <dd>32-bit unsigned integer - {@link org.opendaylight.yangtools.yang.model.util.Int32}</dd>
+ * <dt>uint64</dt>
+ * <dd>64-bit unsigned integer -{@link org.opendaylight.yangtools.yang.model.util.Int64}</dd>
+ * <dt>instance-identifier</dt>
+ * <dd>References a data tree node - {@link org.opendaylight.yangtools.yang.model.util.InstanceIdentifier}</dd>
+ * <dt>string</dt>
+ * <dd>{@link org.opendaylight.yangtools.yang.model.util.StringType}</dd>
+ * </dl>
+ *
+ * Common trait of base types with default instance is, that there is no requirement
+ * for user input in YANG schema to further modify this types.
+ * <p>
+ * The implementation classes for these base types contains static method <code>getInstance()</code>
+ * which provides reusable {@link org.opendaylight.yangtools.concepts.Immutable} instance of type.
+ *
+ * <h3>Base built-in types without default instance</h3>
+ *
+ * <dl>
+ * <dt>bits</dt>
+ * <dd>A set of bits or flags - {@link org.opendaylight.yangtools.yang.model.util.BitsType}</dd>
+ * <dt>decimal64</dt>
+ * <dd>64-bit signed decimal number - {@link org.opendaylight.yangtools.yang.model.util.Decimal64}</dd>
+ * <dt>enumeration</dt>
+ * <dd>Enumerated strings - {@link org.opendaylight.yangtools.yang.model.util.EnumerationType}</dd>
+ * <dt>union</dt>
+ * <dd>Choice of member types - {@link org.opendaylight.yangtools.yang.model.util.UnionType}</dd>
+ * <dt>identity-ref</dt>
+ * <dd>A reference to an abstract identity - {@link org.opendaylight.yangtools.yang.model.util.IdentityrefType}</dd>
+ * <dt>leafref</dt>
+ * <dd>A reference to a leaf instance - {@link org.opendaylight.yangtools.yang.model.util.Leafref}</dd>
+ * </dl>
+ *
+ * Common trait of these base types without default instance is, that they require
+ * user input in YANG schema to create instance of this types, and may have infinity number of
+ * possible permutations.
+ * <p>
+ * The implementations have static factory method <code>create(SchemaPath,...)</code>
+ * which provides {@link org.opendaylight.yangtools.concepts.Immutable} instance of type.
+ *
+ */
+package org.opendaylight.yangtools.yang.model.util;
\ No newline at end of file
package org.opendaylight.yangtools.yang.model.util.repo;
import org.opendaylight.yangtools.concepts.Delegator;
+
+import com.google.common.annotations.Beta;
import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
-import static com.google.common.base.Preconditions.*;
+/**
+ *
+ * Abstract caching schema provider with support of multiple context
+ * per backing {@link SchemaSourceProvider}.
+ *
+ * @param <I> Input Schema Source Representation
+ * @param <O> Output Schema Source Representation
+ */
public abstract class AbstractCachingSchemaSourceProvider<I, O> implements AdvancedSchemaSourceProvider<O>,
Delegator<AdvancedSchemaSourceProvider<I>> {
- public class CompatibilitySchemaSourceProviderInstance implements SchemaSourceProvider<O> {
-
- @Override
- public Optional<O> getSchemaSource(String moduleName, Optional<String> revision) {
- // TODO Auto-generated method stub
- return null;
- }
-
- }
-
private final AdvancedSchemaSourceProvider<I> defaultDelegate;
- protected AbstractCachingSchemaSourceProvider(AdvancedSchemaSourceProvider<I> delegate) {
+ /**
+ * Construct caching schema source provider with supplied delegate.
+ *
+ * Default delegate is is used to retrieve schema source when cache does not
+ * contain requested sources.
+ *
+ * @param delegate SchemaSourceProvided used to look up and retrieve schema source
+ * when cache does not contain requested sources.
+ */
+ protected AbstractCachingSchemaSourceProvider(final AdvancedSchemaSourceProvider<I> delegate) {
this.defaultDelegate = delegate;
}
@Override
- public Optional<O> getSchemaSource(String moduleName, Optional<String> revision) {
- checkNotNull(moduleName, "Module name should not be null.");
- checkNotNull(revision, "Revision should not be null");
+ public Optional<O> getSchemaSource(final String moduleName, final Optional<String> revision) {
+ Preconditions.checkNotNull(moduleName, "Module name should not be null.");
+ Preconditions.checkNotNull(revision, "Revision should not be null");
return getSchemaSource(SourceIdentifier.create(moduleName, revision));
}
-
+
@Override
- public Optional<O> getSchemaSource(SourceIdentifier sourceIdentifier) {
+ public Optional<O> getSchemaSource(final SourceIdentifier sourceIdentifier) {
return getSchemaSourceImpl(sourceIdentifier, defaultDelegate);
}
- protected final Optional<O> getSchemaSourceImpl(SourceIdentifier identifier,
- AdvancedSchemaSourceProvider<I> delegate) {
- checkNotNull(identifier, "Source identifier name should not be null.");
+ /**
+ * Actual implementation of schema source retrieval.
+ *
+ * <ul>
+ * <li>look up cached schema source via {@link #getCachedSchemaSource(SourceIdentifier)}
+ * <li>If source was found in cache, returns source to client code.
+ * <li>If source was not found in cache, Look up schema source in supplied <code>delegate</code>
+ * <li>Updates cache with schema from delegate by {@link #cacheSchemaSource(SourceIdentifier, Optional)}
+ * <li>Result is returned to client code.
+ * </ul>
+ *
+ * @param identifier Source identifier
+ * @param delegate Delegate to lookup if there is a miss.
+ * @return Optional of schema source, present if source was found. Absent otherwise.
+ */
+ protected final Optional<O> getSchemaSourceImpl(final SourceIdentifier identifier,
+ final AdvancedSchemaSourceProvider<I> delegate) {
+ Preconditions.checkNotNull(identifier, "Source identifier name should not be null.");
Optional<O> cached = getCachedSchemaSource(identifier);
if (cached.isPresent()) {
return cacheSchemaSource(identifier, live);
}
- abstract protected Optional<O> cacheSchemaSource(SourceIdentifier identifier, Optional<I> stream);
-
+ /**
+ * Caches supplied result and returns cached result which should be returned to client.
+ *
+ * <p>
+ * Implementations of cache are required to cache schema source if possible.
+ * They are not required to cache {@link Optional#absent()}.
+ *
+ * Implementations are required to transform source representation if <code>O</code> and <code>I</code>
+ * are different.
+ *
+ * This method SHOULD NOT fail and should recover from Runtime exceptions
+ * by not caching source and only transforming it.
+ *
+ * @param identifier Source Identifier for which schema SHOULD be cached
+ * @param input Optional of schema source, representing one returned from delegate.
+ * @return Optional of schema source, representing result returned from this cache.
+ */
+ abstract protected Optional<O> cacheSchemaSource(SourceIdentifier identifier, Optional<I> input);
+
+ /**
+ * Returns cached schema source of {@link Optional#absent()} if source is not present in cache.
+ *
+ * <p>
+ * Implementations of cache MUST return cached schema source, if it is present in cache,
+ * otherwise source will be requested from deleate and then cache will be updated
+ * via {@link #cacheSchemaSource(SourceIdentifier, Optional)}.
+ *
+ * @param identifier Source Identifier for which schema should be retrieved.
+ * @return Cached schema source.
+ */
abstract protected Optional<O> getCachedSchemaSource(SourceIdentifier identifier);
+ @Override
public AdvancedSchemaSourceProvider<I> getDelegate() {
return defaultDelegate;
}
- public SchemaSourceProvider<O> createInstanceFor(SchemaSourceProvider<I> delegate) {
- checkNotNull(delegate, "Delegate should not be null");
+ /**
+ * Creates an lightweight instance of source provider, which uses this cache for caching
+ * and supplied additional delegate for lookup of not cached sources.
+ * <p>
+ *
+ * @param delegate Backing {@link SchemaSourceProvider} which should be used for lookup
+ * for sources not present in schema.
+ * @return new instance of {@link SchemaSourceProvider} which first lookup in cache
+ * and then in delegate.
+ *
+ */
+ @Beta
+ public SchemaSourceProvider<O> createInstanceFor(final SchemaSourceProvider<I> delegate) {
return new SchemaSourceProviderInstance(SchemaSourceProviders.toAdvancedSchemaSourceProvider(delegate));
-
+
}
+ /**
+ *
+ * Lightweight instance of source provider, which is associated with parent
+ * {@link AbstractCachingSchemaSourceProvider}, but uses
+ * different delegate for retrieving not cached sources.
+ *
+ */
+ @Beta
private class SchemaSourceProviderInstance implements //
- AdvancedSchemaSourceProvider<O>,
+ AdvancedSchemaSourceProvider<O>,
Delegator<AdvancedSchemaSourceProvider<I>> {
private final AdvancedSchemaSourceProvider<I> delegate;
- protected SchemaSourceProviderInstance(AdvancedSchemaSourceProvider<I> delegate) {
+ protected SchemaSourceProviderInstance(final AdvancedSchemaSourceProvider<I> delegate) {
super();
- this.delegate = delegate;
+ this.delegate = Preconditions.checkNotNull(delegate, "Delegate should not be null");;
}
@Override
- public Optional<O> getSchemaSource(String moduleName, Optional<String> revision) {
+ public Optional<O> getSchemaSource(final String moduleName, final Optional<String> revision) {
return getSchemaSource(SourceIdentifier.create(moduleName, revision));
}
}
@Override
- public Optional<O> getSchemaSource(SourceIdentifier sourceIdentifier) {
+ public Optional<O> getSchemaSource(final SourceIdentifier sourceIdentifier) {
return getSchemaSourceImpl(sourceIdentifier, getDelegate());
}
}
import com.google.common.base.Optional;
-public interface AdvancedSchemaSourceProvider<F> extends SchemaSourceProvider<F> {
+/**
+ * Provider of representation of YANG schema sources.
+ *
+ * <p>
+ * {@link AdvancedSchemaSourceProvider} is extension of
+ * {@link SchemaSourceProvider} which did not have object concept of source
+ * identifier, and introduces {@link SourceIdentifier} (which contains schema
+ * name and revision) as identifier of sources.
+ *
+ * <p>
+ * <b>Schema Source representation</b>
+ * <p>
+ * Representation of schema source. Representation of schema source could exists
+ * in various formats (Java types), depending on stage of processing, but
+ * representation MUST BE still result of processing of only single unit of schema
+ * source (file, input stream). E.g.:
+ * <ul>
+ * <li>{@link java.lang.String} - textual representation of source code
+ * <li>{@link java.io.InputStream} - input stream containing source code
+ * <li>{@link com.google.common.io.ByteSource} - source for input streams
+ * containing source code
+ * <li>Parsed AST - abstract syntax tree, which is result of a parser, but still
+ * it is not linked against other schemas.
+ *
+ * <p>
+ * Conversion between representations should be done via implementations of
+ * {@link SchemaSourceTransformation}.
+ *
+ * @param <T>
+ * Schema source representation type provided by this implementation
+ */
+public interface AdvancedSchemaSourceProvider<T> extends SchemaSourceProvider<T> {
- Optional<F> getSchemaSource(SourceIdentifier sourceIdentifier);
+ /**
+ * Returns representation source for supplied YANG source identifier.
+ *
+ * Returned representation of schema source must be immutable, must not
+ * change during runtime if {@link SourceIdentifier} has specified both
+ * {@link SourceIdentifier#getName()} and
+ * {@link SourceIdentifier#getRevision()}
+ *
+ * @param sourceIdentifier
+ * source identifier.
+ * @return source representation if supplied YANG module is available
+ * {@link Optional#absent()} otherwise.
+ */
+ Optional<T> getSchemaSource(SourceIdentifier sourceIdentifier);
}
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
-public class FilesystemSchemaCachingProvider<I> extends AbstractCachingSchemaSourceProvider<I, InputStream> {
+/**
+ * Filesystem-based schema caching source provider
+ *
+ * This schema source provider caches all YANG modules loaded from backing
+ * schema source providers (registered via
+ * {@link #createInstanceFor(SchemaSourceProvider)} to supplied folder.
+ *
+ * @param <I>
+ * Input format in which schema source is represented.
+ *
+ */
+public final class FilesystemSchemaCachingProvider<I> extends AbstractCachingSchemaSourceProvider<I, InputStream> {
private static final Logger LOG = LoggerFactory.getLogger(FilesystemSchemaCachingProvider.class);
private final File storageDirectory;
- private final Function<I, String> transformationFunction;
+ private final SchemaSourceTransformation<I, String> transformationFunction;
+
+ /**
+ *
+ * Construct filesystem caching schema source provider.
+ *
+ *
+ * @param delegate
+ * Default delegate to lookup for missed entries in cache.
+ * @param directory
+ * Directory where YANG files should be cached.
+ * @param transformationFunction
+ * Transformation function which translates from input in format
+ * <code>I</code> to InputStream.
+ * @throws IllegalArgumentException
+ * If supplied directory does not exists or is not directory.
+ */
+ public FilesystemSchemaCachingProvider(final AdvancedSchemaSourceProvider<I> delegate, final File directory,
+ final SchemaSourceTransformation<I, String> transformationFunction) {
+ super(delegate);
+ Preconditions.checkNotNull(directory, "directory must not be null.");
+ Preconditions.checkArgument(directory.exists(), "directory must be directory.");
+ Preconditions.checkArgument(directory.isDirectory(), "directory must be directory.");
+ this.storageDirectory = directory;
+ this.transformationFunction = Preconditions.checkNotNull(transformationFunction,
+ "transformationFunction must not be null.");
+ }
+ /**
+ *
+ * Construct filesystem caching schema source provider.
+ *
+ *
+ * @param delegate
+ * Default delegate to lookup for missed entries in cache.
+ * @param directory
+ * Directory where YANG files should be cached.
+ * @param transformationFunction
+ * Transformation function which translates from input in format
+ * <code>I</code> to InputStream.
+ * @throws IllegalArgumentException
+ * If supplied directory does not exists or is not directory.
+ * @deprecated Use
+ * {@link #FilesystemSchemaCachingProvider(AdvancedSchemaSourceProvider, File, SchemaSourceTransformation)}
+ * with
+ * {@link SchemaSourceProviders#schemaSourceTransformationFrom(Function)}
+ * instead.
+ */
+ @Deprecated
public FilesystemSchemaCachingProvider(final AdvancedSchemaSourceProvider<I> delegate, final File directory,
final Function<I, String> transformationFunction) {
super(delegate);
+ Preconditions.checkNotNull(directory, "directory must not be null.");
+ Preconditions.checkArgument(directory.exists(), "directory must be directory.");
+ Preconditions.checkArgument(directory.isDirectory(), "directory must be directory.");
this.storageDirectory = directory;
- this.transformationFunction = transformationFunction;
+ this.transformationFunction = SchemaSourceProviders.schemaSourceTransformationFrom(transformationFunction);
}
@Override
- protected synchronized Optional<InputStream> cacheSchemaSource(final SourceIdentifier identifier, final Optional<I> source) {
+ protected synchronized Optional<InputStream> cacheSchemaSource(final SourceIdentifier identifier,
+ final Optional<I> source) {
File schemaFile = toFile(identifier);
try {
if (source.isPresent() && schemaFile.createNewFile()) {
writer.write(transformToString(source.get()));
writer.flush();
} catch (IOException e) {
-
+ LOG.warn("Could not chache source for {}. Source: ",identifier,source.get(),e);
}
}
} catch (IOException e) {
-
+ LOG.warn("Could not create cache file for {}. File: ",identifier,schemaFile,e);
}
return transformToStream(source);
}
private Optional<InputStream> transformToStream(final Optional<I> source) {
if (source.isPresent()) {
- return Optional.<InputStream> of(
- new ByteArrayInputStream(transformToString(source.get()).getBytes(Charsets.UTF_8)));
+ return Optional.<InputStream> of(new ByteArrayInputStream(transformToString(source.get()).getBytes(
+ Charsets.UTF_8)));
}
return Optional.absent();
}
private String transformToString(final I input) {
- return transformationFunction.apply(input);
+ return transformationFunction.transform(input);
}
@Override
private File findFileWithNewestRev(final SourceIdentifier identifier) {
File[] files = storageDirectory.listFiles(new FilenameFilter() {
final String regex = identifier.getName() + "(\\.yang|@\\d\\d\\d\\d-\\d\\d-\\d\\d.yang)";
+
@Override
public boolean accept(final File dir, final String name) {
if (name.matches(regex)) {
return file;
}
- private static final Function<String, String> NOOP_TRANSFORMATION = new Function<String, String>() {
- @Override
- public String apply(final String input) {
- return input;
- }
- };
-
public static FilesystemSchemaCachingProvider<String> createFromStringSourceProvider(
final SchemaSourceProvider<String> liveProvider, final File directory) {
Preconditions.checkNotNull(liveProvider);
return new FilesystemSchemaCachingProvider<String>(
SchemaSourceProviders.toAdvancedSchemaSourceProvider(liveProvider),//
directory, //
- NOOP_TRANSFORMATION);
+ SchemaSourceProviders.<String>identityTransformation());
}
}
package org.opendaylight.yangtools.yang.model.util.repo;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextHolder;
+
+/**
+ * Represent Schema Service.
+ *
+ *
+ * @deprecated Replaced by {@link SchemaContextHolder}, which provides
+ * component-local view for actual {@link SchemaContext}.
+ */
+@Deprecated
public interface SchemaService {
-
SchemaContext getSchemaContext();
}
import com.google.common.base.Optional;
+/**
+ * Provider of text stream representation of YANG Modules
+ *
+ * Provider is holder / user implemented service, which
+ * may be able to retrieve representation of YANG sources
+ * for other components.
+ *
+ * @param <F> Format in which YANG source is represented.
+ */
public interface SchemaSourceProvider<F> {
+ /**
+ * Returns source for supplied YANG module identifier and revision.
+ *
+ * @param moduleName module name
+ * @param revision revision of module
+ * @return source representation if supplied YANG module is available
+ * {@link Optional#absent()} otherwise.
+ * @deprecated Use {@link AdvancedSchemaSourceProvider#getSchemaSource(SourceIdentifier)}
+ * instead.
+ */
+ @Deprecated
Optional<F> getSchemaSource(String moduleName, Optional<String> revision);
}
import org.opendaylight.yangtools.concepts.Delegator;
import com.google.common.base.Charsets;
+import com.google.common.base.Function;
import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
-public class SchemaSourceProviders {
+/**
+ *
+ * Utility functions for {@link SchemaSourceProvider}
+ *
+ */
+public final class SchemaSourceProviders {
@SuppressWarnings("rawtypes")
private static final SchemaSourceProvider NOOP_PROVIDER = new AdvancedSchemaSourceProvider() {
};
+ @SuppressWarnings("rawtypes")
+ private static final SchemaSourceTransformation IDENTITY_TRANFORMATION = new IdentityTransformation();
+
+ private static final StringToInputStreamTransformation STRING_TO_INPUTSTREAM_TRANSFORMATION = new StringToInputStreamTransformation();
+
+ private SchemaSourceProviders() {
+ throw new UnsupportedOperationException("Utility class.");
+ }
+
+ /**
+ * Returns a noop schema source provider.
+ *
+ * Noop schema provider returns {@link Optional#absent()} for each call to
+ * query schema source.
+ *
+ * @return
+ */
@SuppressWarnings("unchecked")
public static <T> SchemaSourceProvider<T> noopProvider() {
return NOOP_PROVIDER;
}
+ /**
+ *
+ * Returns delegating schema source provider which returns InputStream from
+ * supplied String based schema source provider.
+ *
+ * @param delegate
+ * @return
+ */
public static SchemaSourceProvider<InputStream> inputStreamProviderfromStringProvider(
final AdvancedSchemaSourceProvider<String> delegate) {
- return new StringToInputStreamSchemaSourceProvider(delegate);
+ return TransformingSourceProvider.create(delegate, STRING_TO_INPUTSTREAM_TRANSFORMATION);
}
- public static <O> AdvancedSchemaSourceProvider<O> toAdvancedSchemaSourceProvider(final SchemaSourceProvider<O> schemaSourceProvider) {
+ /**
+ * Returns identity implementation of SchemaSourceTransformation
+ *
+ * Identity implementation of SchemaSourceTransformation is useful
+ * for usecases where Input and Output of SchemaSourceTransformation
+ * are identitcal, and you want to reuse input as an output.
+ *
+ * This implementation is really simple <code>return input;</code>.
+ *
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public static <I> SchemaSourceTransformation<I, I> identityTransformation() {
+ return IDENTITY_TRANFORMATION;
+ }
+
+ public static <I, O> SchemaSourceTransformation<I, O> schemaSourceTransformationFrom(
+ final Function<I, O> transformation) {
+ return new FunctionBasedSchemaSourceTransformation<I, O>(transformation);
+ }
+
+ /**
+ *
+ * Casts {@link SchemaSourceProvider} to
+ * {@link AdvancedSchemaSourceProvider} or wraps it with utility
+ * implementation if supplied delegate does not implement
+ * {@link AdvancedSchemaSourceProvider}.
+ *
+ * @param schemaSourceProvider
+ */
+ public static <O> AdvancedSchemaSourceProvider<O> toAdvancedSchemaSourceProvider(
+ final SchemaSourceProvider<O> schemaSourceProvider) {
if (schemaSourceProvider instanceof AdvancedSchemaSourceProvider<?>) {
return (AdvancedSchemaSourceProvider<O>) schemaSourceProvider;
}
return new SchemaSourceCompatibilityWrapper<O>(schemaSourceProvider);
}
- private final static class StringToInputStreamSchemaSourceProvider implements //
- AdvancedSchemaSourceProvider<InputStream>, Delegator<AdvancedSchemaSourceProvider<String>> {
+ private static final class FunctionBasedSchemaSourceTransformation<I, O> implements
+ SchemaSourceTransformation<I, O> {
- private final AdvancedSchemaSourceProvider<String> delegate;
- public StringToInputStreamSchemaSourceProvider(final AdvancedSchemaSourceProvider<String> delegate) {
- this.delegate = delegate;
- }
+ private final Function<I, O> delegate;
- @Override
- public AdvancedSchemaSourceProvider<String> getDelegate() {
- return delegate;
+ protected FunctionBasedSchemaSourceTransformation(final Function<I, O> delegate) {
+ super();
+ this.delegate = Preconditions.checkNotNull(delegate, "delegate MUST NOT be null.");
}
@Override
- public Optional<InputStream> getSchemaSource(final SourceIdentifier sourceIdentifier) {
- Optional<String> potentialSource = getDelegate().getSchemaSource(sourceIdentifier);
- if (potentialSource.isPresent()) {
- final String stringSource = potentialSource.get();
- return Optional.<InputStream> of(
- new ByteArrayInputStream(stringSource.getBytes(Charsets.UTF_8)));
- }
- return Optional.absent();
+ public O transform(final I input) {
+ return delegate.apply(input);
}
@Override
- public Optional<InputStream> getSchemaSource(final String moduleName, final Optional<String> revision) {
- return getSchemaSource(SourceIdentifier.create(moduleName, revision));
+ public String toString() {
+ return "FunctionBasedSchemaSourceTransformation [delegate=" + delegate + "]";
}
}
return delegate;
}
+
+ /*
+ * Deprecation warnings are suppresed, since this implementation
+ * needs to invoke deprecated method in order to provide
+ * implementation of non-deprecated APIs using legacy ones.
+ *
+ * (non-Javadoc)
+ * @see org.opendaylight.yangtools.yang.model.util.repo.AdvancedSchemaSourceProvider#getSchemaSource(org.opendaylight.yangtools.yang.model.util.repo.SourceIdentifier)
+ */
+ @SuppressWarnings("deprecation")
@Override
public Optional<O> getSchemaSource(final SourceIdentifier sourceIdentifier) {
return delegate.getSchemaSource(moduleName, revision);
}
+ /*
+ * Deprecation warnings are suppresed, since this implementation
+ * needs to invoke deprecated method in order to provide
+ * implementation of non-deprecated APIs using legacy ones.
+ *
+ * (non-Javadoc)
+ * @see org.opendaylight.yangtools.yang.model.util.repo.AdvancedSchemaSourceProvider#getSchemaSource(org.opendaylight.yangtools.yang.model.util.repo.SourceIdentifier)
+ */
@Override
+ @SuppressWarnings("deprecation")
public Optional<O> getSchemaSource(final String moduleName, final Optional<String> revision) {
return delegate.getSchemaSource(moduleName, revision);
}
}
+ @SuppressWarnings("rawtypes")
+ private static class IdentityTransformation implements SchemaSourceTransformation {
+
+ @Override
+ public Object transform(final Object input) {
+ return input;
+ }
+ }
+
+ private static class StringToInputStreamTransformation implements SchemaSourceTransformation<String, InputStream> {
+
+ @Override
+ public InputStream transform(final String input) {
+ return new ByteArrayInputStream(input.getBytes(Charsets.UTF_8));
+ }
+
+ }
+
}
--- /dev/null
+/*
+ * Copyright (c) 2014 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/eplv10.html
+ */
+package org.opendaylight.yangtools.yang.model.util.repo;
+
+import com.google.common.annotations.Beta;
+
+/**
+ *
+ * Schema Source Transformation which transforms from one schema source
+ * representation to another.
+ *
+ * <p>
+ * <b>Representation of Schema Source</b>
+ * <p>
+ * Schema source may be represented by
+ * various Java Types, which depends on provider and/or consumer.
+ * <p>
+ * E.g example of possible representations:
+ * <ul>
+ * <li>{@link String}
+ * <li>{@link java.io.InputStream}
+ * <li>{@link com.google.common.io.ByteSource}
+ * </ul>
+ *
+ * FIXME: <b>Beta:</b> Consider allowing transformations, which may
+ * fail to produce Output, this will require introduction of
+ * checked exception.
+ *
+ * @param <I> Input schema source representation
+ * @param <O> Output schema source representation
+ */
+@Beta
+public interface SchemaSourceTransformation<I, O> {
+
+ /**
+ *
+ * Transforms supplied schema source in format <code>I</code> to schema
+ * source in format <code>O</code>.
+ *
+ * <ul>
+ * <li>Its execution does not cause any observable side effects.
+ * <li>If the contents of a,b are semantically same (e.g. contents of InputStream),
+ * output representations MUST BE also semantically equals.
+ * </ul>
+ *
+ * Implementations of transformation SHOULD NOT fail to
+ * transform valid non-null input to output representation.
+ *
+ *
+ * FIXME: <b>Beta:</b> Consider lowering condition for safe transformation
+ * and introduce checked exception for cases when transformation may fail.
+ *
+ * @param input Not null input which should be transformed
+ * @return Representation of input in <code>O</code> format.
+ * @throws NullPointerException if input is null.
+ *
+ */
+ @Beta
+ O transform(I input);
+}
*/
package org.opendaylight.yangtools.yang.model.util.repo;
+import org.opendaylight.yangtools.concepts.Immutable;
+
import com.google.common.base.Optional;
-public final class SourceIdentifier {
+/**
+ *
+ * YANG Schema source identifier
+ *
+ * Simple transfer object represents identifier of source for YANG schema (module or submodule),
+ * which consists of
+ * <ul>
+ * <li>YANG schema name ({@link #getName()}
+ * <li>Module revision (optional) ({link {@link #getRevision()})
+ * </ul>
+ *
+ * Source identifier is designated to be carry only necessary information
+ * to look-up YANG model source and to be used by {@link AdvancedSchemaSourceProvider}
+ * and similar.
+ *
+ * <b>Note:</b>On source retrieval layer it is impossible to distinguish
+ * between YANG module and/or submodule unless source is present.
+ *
+ * <p>
+ * (For further reference see: http://tools.ietf.org/html/rfc6020#section-5.2 and
+ * http://tools.ietf.org/html/rfc6022#section-3.1 ).
+ *
+ *
+ */
+public final class SourceIdentifier implements Immutable {
private final String name;
private final String revision;
+ /**
+ *
+ * Creates new YANG Schema source identifier.
+ *
+ * @param name Name of schema
+ * @param formattedRevision Revision of source in format YYYY-mm-dd
+ */
public SourceIdentifier(final String name, final Optional<String> formattedRevision) {
super();
this.name = name;
this.revision = formattedRevision.orNull();
}
+ /**
+ * Returns model name
+ *
+ * @return model name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns revision of source or null if revision was not supplied.
+ *
+ * @return revision of source or null if revision was not supplied.
+ */
+ public String getRevision() {
+ return revision;
+ }
+
@Override
public int hashCode() {
final int prime = 31;
return true;
}
- public String getName() {
- return name;
- }
-
- public String getRevision() {
- return revision;
- }
-
public static SourceIdentifier create(final String moduleName, final Optional<String> revision) {
return new SourceIdentifier(moduleName, revision);
}
+ /**
+ * Returns filename for this YANG module as specified in RFC 6020.
+ *
+ * Returns filename in format
+ * <code>name ['@' revision] '.yang'</code>
+ * <p>
+ * Where revision is date in format YYYY-mm-dd.
+ * <p>
+ * See
+ * http://tools.ietf.org/html/rfc6020#section-5.2
+ *
+ * @return Filename for this source identifier.
+ */
public String toYangFilename() {
return toYangFileName(name, Optional.fromNullable(revision));
}
return "SourceIdentifier [name=" + name + "@" + revision + "]";
}
+ /**
+ * Returns filename for this YANG module as specified in RFC 6020.
+ *
+ * Returns filename in format
+ * <code>moduleName ['@' revision] '.yang'</code>
+ *
+ * Where Where revision-date is in format YYYY-mm-dd.
+ *
+ * <p>
+ * See
+ * http://tools.ietf.org/html/rfc6020#section-5.2
+ *
+ * @return Filename for this source identifier.
+ */
public static final String toYangFileName(final String moduleName, final Optional<String> revision) {
StringBuilder filename = new StringBuilder(moduleName);
if (revision.isPresent()) {
--- /dev/null
+package org.opendaylight.yangtools.yang.model.util.repo;
+
+import org.opendaylight.yangtools.concepts.Delegator;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ *
+ * Utility Source Provider implementation which uses delegate to retrieve
+ * sources and transformation function to convert sources to different
+ * representation.
+ *
+ *
+ * @param <I>
+ * Representation of schema sources used by delegate
+ * @param <O>
+ * Representation of schema sources exposed by this provider
+ */
+public final class TransformingSourceProvider<I, O> implements //
+ AdvancedSchemaSourceProvider<O>, Delegator<AdvancedSchemaSourceProvider<I>> {
+
+ private final AdvancedSchemaSourceProvider<I> delegate;
+ private final SchemaSourceTransformation<I, O> transformation;
+
+ /**
+ * Creates instance of transforming schema source provider which uses
+ * supplied delegate to retrieve sources and transformation to change
+ * sources to different representation.
+ *
+ * @param delegate
+ * Delegate which provides sources.
+ * @param transformation
+ * Transformation function which converts sources
+ * @return Instance of TransformingSourceProvider
+ * @throws NullPointerException
+ * if any of arguments is null.
+ */
+ public static final <I, O> TransformingSourceProvider<I, O> create(final AdvancedSchemaSourceProvider<I> delegate,
+ final SchemaSourceTransformation<I, O> transformation) {
+ return new TransformingSourceProvider<>(delegate, transformation);
+ }
+
+ private TransformingSourceProvider(final AdvancedSchemaSourceProvider<I> delegate,
+ final SchemaSourceTransformation<I, O> transformation) {
+ this.delegate = Preconditions.checkNotNull(delegate, "delegate must not be null");
+ this.transformation = Preconditions.checkNotNull(transformation, "transformation must not be null");
+ }
+
+ @Override
+ public AdvancedSchemaSourceProvider<I> getDelegate() {
+ return delegate;
+ }
+
+ @Override
+ public Optional<O> getSchemaSource(final SourceIdentifier sourceIdentifier) {
+ Optional<I> potentialSource = getDelegate().getSchemaSource(sourceIdentifier);
+ if (potentialSource.isPresent()) {
+ I inputSource = potentialSource.get();
+ return Optional.<O> of(transformation.transform(inputSource));
+ }
+ return Optional.absent();
+ }
+
+ @Override
+ public Optional<O> getSchemaSource(final String moduleName, final Optional<String> revision) {
+ return getSchemaSource(SourceIdentifier.create(moduleName, revision));
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2014 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/eplv10.html
+ */
+/**
+ * This package introduces concepts, generic interfaces and implementations for
+ * creating and working with YANG Schema source repositories and working with them.
+ *
+ * <h2>Concepts</h2>
+ * <dl>
+ * <dt>Schema Source</dt>
+ * <dd>Source of YANG Schema, which is not processed, not resolved against other schemas
+ * and from contents of <i>Schema Source</i> in combination with other Schema sources
+ * it is possible to create resolved YANG Schema context.
+ * </dd>
+ * <dt>{@link org.opendaylight.yangtools.yang.model.util.repo.SourceIdentifier}</dt>
+ * <dd>Identifier of Schema Source. Identifier is not tied with source or representation.</dd>
+ * <dt>Schema Source Representation</dt>
+ * <dd>Representation of schema source. Representation of schema source could exists in various
+ * formats (Java types), depending on stage of processing, but representation MUST BE
+ * still result of processing only single unit of schema source (e.g. file, input stream). E.g.:
+ * <ul>
+ * <li>{@link java.lang.String} - textual representation of source code
+ * <li>{@link InputStream} - input stream containing source code
+ * <li>{@link com.google.common.io.ByteSource} - source for input streams containing source code
+ * <li>Parsed AST - abstract syntax tree, which is result of a parser, but still it is not linked
+ * against other schemas.
+ * </ul>
+ * </dd>
+ * <dt>{@link org.opendaylight.yangtools.yang.model.util.repo.AdvancedSchemaSourceProvider}</dt>
+ * <dd>
+ * Service which provides query API to obtain <i>Schema Source Representation</i> associated
+ * with {@link org.opendaylight.yangtools.yang.model.util.repo.SourceIdentifier}.
+ * </dd>
+ * <dt>{@link org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceTransformation}</dt>
+ * <dd>
+ * Function (service) which provides transformation from one <i>Schema Source Representation</i>
+ * type to another.
+ * </dd>
+ * </dl>
+ *
+ *
+ */
+package org.opendaylight.yangtools.yang.model.util.repo;
\ No newline at end of file
/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
+ * 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
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.HashBiMap;
import com.google.common.io.ByteSource;
-
public final class YangParserImpl implements YangContextParser {
private static final Logger LOG = LoggerFactory.getLogger(YangParserImpl.class);
}
@Override
- public SchemaContext parseFile(final File yangFile, final File directory) throws IOException, YangSyntaxErrorException {
+ public SchemaContext parseFile(final File yangFile, final File directory) throws IOException,
+ YangSyntaxErrorException {
Preconditions.checkState(yangFile.exists(), yangFile + " does not exists");
Preconditions.checkState(directory.exists(), directory + " does not exists");
Preconditions.checkState(directory.isDirectory(), directory + " is not a directory");
}
@Override
- public SchemaContext parseFiles(final Collection<File> yangFiles, final SchemaContext context) throws IOException, YangSyntaxErrorException {
+ public SchemaContext parseFiles(final Collection<File> yangFiles, final SchemaContext context) throws IOException,
+ YangSyntaxErrorException {
if (yangFiles == null) {
return resolveSchemaContext(Collections.<Module> emptySet());
}
}
@Override
- public SchemaContext parseSources(final Collection<ByteSource> sources) throws IOException, YangSyntaxErrorException {
+ public SchemaContext parseSources(final Collection<ByteSource> sources) throws IOException,
+ YangSyntaxErrorException {
Collection<Module> unsorted = parseYangModelSources(sources).values();
Set<Module> sorted = new LinkedHashSet<>(
ModuleDependencySort.sort(unsorted.toArray(new Module[unsorted.size()])));
}
@Override
- public SchemaContext parseSources(final Collection<ByteSource> sources, final SchemaContext context) throws IOException, YangSyntaxErrorException {
+ public SchemaContext parseSources(final Collection<ByteSource> sources, final SchemaContext context)
+ throws IOException, YangSyntaxErrorException {
if (sources == null) {
return resolveSchemaContext(Collections.<Module> emptySet());
}
@Override
public SchemaContext resolveSchemaContext(final Set<Module> modules) {
- // after merging parse method with this one, add support for getting submodule sources.
+ // after merging parse method with this one, add support for getting
+ // submodule sources.
Map<ModuleIdentifier, String> identifiersToSources = new HashMap<>();
- for(Module module: modules) {
+ for (Module module : modules) {
ModuleImpl moduleImpl = (ModuleImpl) module;
identifiersToSources.put(module, moduleImpl.getSource());
}
return new SchemaContextImpl(modules, identifiersToSources);
}
- private Map<ByteSource, Module> parseYangModelSources(final Collection<ByteSource> sources) throws IOException, YangSyntaxErrorException {
+ private Map<ByteSource, Module> parseYangModelSources(final Collection<ByteSource> sources) throws IOException,
+ YangSyntaxErrorException {
if (sources == null || sources.isEmpty()) {
return Collections.emptyMap();
}
* parsed from stream
* @throws YangSyntaxErrorException
*/
- private Map<ByteSource, ModuleBuilder> resolveSources(final Collection<ByteSource> streams) throws IOException, YangSyntaxErrorException {
+ private Map<ByteSource, ModuleBuilder> resolveSources(final Collection<ByteSource> streams) throws IOException,
+ YangSyntaxErrorException {
Map<ByteSource, ModuleBuilder> builders = parseSourcesToBuilders(streams);
Map<ByteSource, ModuleBuilder> result = resolveSubmodules(builders);
return result;
}
- private Map<ByteSource, ModuleBuilder> parseSourcesToBuilders(final Collection<ByteSource> sources) throws IOException, YangSyntaxErrorException {
+ private Map<ByteSource, ModuleBuilder> parseSourcesToBuilders(final Collection<ByteSource> sources)
+ throws IOException, YangSyntaxErrorException {
final ParseTreeWalker walker = new ParseTreeWalker();
final Map<ByteSource, ParseTree> sourceToTree = parseYangSources(sources);
final Map<ByteSource, ModuleBuilder> sourceToBuilder = new LinkedHashMap<>();
}
private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuilders(
- final Collection<ByteSource> yangFileStreams, final SchemaContext context) throws IOException, YangSyntaxErrorException {
+ final Collection<ByteSource> yangFileStreams, final SchemaContext context) throws IOException,
+ YangSyntaxErrorException {
Map<ByteSource, ModuleBuilder> parsedBuilders = resolveSources(yangFileStreams);
ModuleBuilder[] builders = new ModuleBuilder[parsedBuilders.size()];
parsedBuilders.values().toArray(builders);
* @param filtered
* collection to fill up
*/
- private void filterImports(final ModuleBuilder main, final Collection<ModuleBuilder> other, final Collection<ModuleBuilder> filtered) {
+ private void filterImports(final ModuleBuilder main, final Collection<ModuleBuilder> other,
+ final Collection<ModuleBuilder> filtered) {
Set<ModuleImport> imports = main.getModuleImports();
// if this is submodule, add parent to filtered and pick its imports
}
}
- private Map<ByteSource, ParseTree> parseYangSources(final Collection<ByteSource> sources) throws IOException, YangSyntaxErrorException {
+ private Map<ByteSource, ParseTree> parseYangSources(final Collection<ByteSource> sources) throws IOException,
+ YangSyntaxErrorException {
final Map<ByteSource, ParseTree> trees = new HashMap<>();
for (ByteSource source : sources) {
trees.put(source, parseYangSource(source));
}
private YangContext parseYangSource(final ByteSource source) throws IOException, YangSyntaxErrorException {
- try (InputStream stream = source.openStream()) {
+ try (InputStream stream = source.openStream()) {
final ANTLRInputStream input = new ANTLRInputStream(stream);
final YangLexer lexer = new YangLexer(input);
final CommonTokenStream tokens = new CommonTokenStream(lexer);
errorListener.validate();
return result;
- }
+ }
}
public static YangContext parseStreamWithoutErrorListeners(final InputStream yangStream) {
}
}
if (node instanceof ChoiceBuilder) {
- for (ChoiceCaseBuilder child : ((ChoiceBuilder)node).getCases()) {
+ for (ChoiceCaseBuilder child : ((ChoiceBuilder) node).getCases()) {
correctPathForAugmentNodes(child, node.getPath());
}
}
UsesNodeBuilder usesNode = (UsesNodeBuilder) augment.getParent();
DataNodeContainerBuilder parentNode = usesNode.getParent();
- SchemaNodeBuilder targetNode;
- if (parentNode instanceof ModuleBuilder) {
- targetNode = findSchemaNodeInModule(augment.getTargetPath().getPath(), (ModuleBuilder) parentNode);
+ Optional<SchemaNodeBuilder> potentialTargetNode;
+ SchemaPath resolvedTargetPath = augment.getTargetNodeSchemaPath();
+ if (parentNode instanceof ModuleBuilder && resolvedTargetPath.isAbsolute()) {
+ // Uses is directly used in module body, we lookup
+ // We lookup in data namespace to find correct augmentation target
+ potentialTargetNode = findSchemaNodeInModule(resolvedTargetPath, (ModuleBuilder) parentNode);
} else {
- targetNode = findSchemaNode(augment.getTargetPath().getPath(), (SchemaNodeBuilder) parentNode);
- }
-
- if (targetNode instanceof AugmentationTargetBuilder) {
- fillAugmentTarget(augment, targetNode);
- ((AugmentationTargetBuilder) targetNode).addAugmentation(augment);
- augment.setResolved(true);
- return true;
+ // Uses is used in local context (be it data namespace or grouping namespace,
+ // since all nodes via uses are imported to localName, it is safe to
+ // to proceed only with local names.
+ //
+ // Conflicting elements in other namespaces are still not present
+ // since resolveUsesAugment occurs before augmenting from external modules.
+ potentialTargetNode = Optional.<SchemaNodeBuilder> fromNullable(findSchemaNode(augment.getTargetPath()
+ .getPath(), (SchemaNodeBuilder) parentNode));
+ }
+
+ if (potentialTargetNode.isPresent()) {
+ SchemaNodeBuilder targetNode = potentialTargetNode.get();
+ if (targetNode instanceof AugmentationTargetBuilder) {
+ fillAugmentTarget(augment, targetNode);
+ ((AugmentationTargetBuilder) targetNode).addAugmentation(augment);
+ augment.setResolved(true);
+ return true;
+ } else {
+ throw new YangParseException(module.getName(), augment.getLine(), String.format(
+ "Failed to resolve augment in uses. Invalid augment target: %s", potentialTargetNode));
+ }
} else {
- throw new YangParseException(module.getName(), augment.getLine(),
- "Failed to resolve augment in uses. Invalid augment target: " + targetNode);
+ throw new YangParseException(module.getName(), augment.getLine(), String.format(
+ "Failed to resolve augment in uses. Invalid augment target path: %s", augment.getTargetPath()));
}
+
}
/**
final String baseIdentityName = identity.getBaseIdentityName();
final int line = identity.getLine();
if (baseIdentityName != null) {
- IdentitySchemaNodeBuilder baseIdentity = findBaseIdentity(modules, module, baseIdentityName, line);
+ IdentitySchemaNodeBuilder baseIdentity = findBaseIdentity(modules, module, baseIdentityName,
+ line);
if (baseIdentity == null) {
- throw new YangParseException(module.getName(), identity.getLine(), "Failed to find base identity");
+ throw new YangParseException(module.getName(), identity.getLine(),
+ "Failed to find base identity");
} else {
identity.setBaseIdentity(baseIdentity);
}
* @param context
* SchemaContext containing already resolved modules
*/
- private void resolveUsesForGroupings(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final SchemaContext context) {
+ private void resolveUsesForGroupings(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ final SchemaContext context) {
final Set<GroupingBuilder> allGroupings = new HashSet<>();
for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
* @param context
* SchemaContext containing already resolved modules
*/
- private void resolveUsesForNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final SchemaContext context) {
+ private void resolveUsesForNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ final SchemaContext context) {
for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
ModuleBuilder module = inner.getValue();
* @param context
* SchemaContext containing already resolved modules
*/
- private void resolveUses(final UsesNodeBuilder usesNode,
- final Map<String, TreeMap<Date, ModuleBuilder>> modules, final SchemaContext context) {
+ private void resolveUses(final UsesNodeBuilder usesNode, final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ final SchemaContext context) {
if (!usesNode.isResolved()) {
DataNodeContainerBuilder parent = usesNode.getParent();
ModuleBuilder module = ParserUtils.getParentModule(parent);
}
/**
- * Copy target grouping child nodes to current location with
- * new namespace.
+ * Copy target grouping child nodes to current location with new namespace.
*
* @param usesNode
* uses node to resolve
rev = module.getRevision();
pref = module.getPrefix();
if (parent instanceof AugmentationSchemaBuilder) {
- parentPath = ((AugmentationSchemaBuilder)parent).getTargetNodeSchemaPath();
+ parentPath = ((AugmentationSchemaBuilder) parent).getTargetNodeSchemaPath();
} else {
- parentPath = ((ModuleBuilder)parent).getPath();
+ parentPath = ((ModuleBuilder) parent).getPath();
}
} else {
ns = ((DataSchemaNodeBuilder) parent).getQName().getNamespace();
rev = ((DataSchemaNodeBuilder) parent).getQName().getRevision();
pref = ((DataSchemaNodeBuilder) parent).getQName().getPrefix();
- parentPath = ((DataSchemaNodeBuilder)parent).getPath();
+ parentPath = ((DataSchemaNodeBuilder) parent).getPath();
}
GroupingDefinition gd = usesNode.getGroupingDefinition();
- Set<DataSchemaNodeBuilder> childNodes = wrapChildNodes(module.getModuleName(), line,
- gd.getChildNodes(), parentPath, ns, rev, pref);
+ Set<DataSchemaNodeBuilder> childNodes = wrapChildNodes(module.getModuleName(), line, gd.getChildNodes(),
+ parentPath, ns, rev, pref);
parent.getChildNodeBuilders().addAll(childNodes);
for (DataSchemaNodeBuilder childNode : childNodes) {
setNodeAddedByUses(childNode);
}
- Set<TypeDefinitionBuilder> typedefs = wrapTypedefs(module.getModuleName(), line, gd, parentPath, ns,
- rev, pref);
+ Set<TypeDefinitionBuilder> typedefs = wrapTypedefs(module.getModuleName(), line, gd, parentPath, ns, rev, pref);
parent.getTypeDefinitionBuilders().addAll(typedefs);
for (TypeDefinitionBuilder typedef : typedefs) {
setNodeAddedByUses(typedef);
}
- Set<GroupingBuilder> groupings = wrapGroupings(module.getModuleName(), line, usesNode
- .getGroupingDefinition().getGroupings(), parentPath, ns, rev, pref);
+ Set<GroupingBuilder> groupings = wrapGroupings(module.getModuleName(), line, usesNode.getGroupingDefinition()
+ .getGroupings(), parentPath, ns, rev, pref);
parent.getGroupingBuilders().addAll(groupings);
for (GroupingBuilder gb : groupings) {
setNodeAddedByUses(gb);
import org.slf4j.LoggerFactory;
import com.google.common.base.Function;
+import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.collect.Collections2;
private static final Logger LOG = LoggerFactory.getLogger(ParserUtils.class);
private static final Splitter SLASH_SPLITTER = Splitter.on('/');
private static final Splitter COLON_SPLITTER = Splitter.on(':');
+ private static final String INPUT = "input";
+ private static final String OUTPUT = "output";
private ParserUtils() {
}
};
}
- public static Collection<ByteSource> filesToByteSources(final Collection<File> streams) throws FileNotFoundException {
+ public static Collection<ByteSource> filesToByteSources(final Collection<File> streams)
+ throws FileNotFoundException {
return Collections2.transform(streams, new Function<File, ByteSource>() {
@Override
public ByteSource apply(final File input) {
try {
stream.close();
} catch (IOException e) {
- LOG.warn("Failed to close stream {}", stream);
+ /*
+ * Failed stream close does not prevent us from
+ * continuing to work correctly, we just report that and
+ * continue.
+ */
+ LOG.warn("Failed to close stream {}. Leaving stream unclosed.", stream, e);
}
}
}
* current line in yang model
* @return module based on given prefix if found in context, null otherwise
*/
- public static Module findModuleFromContext(final SchemaContext context, final ModuleBuilder currentModule, final String prefix,
- final int line) {
+ public static Module findModuleFromContext(final SchemaContext context, final ModuleBuilder currentModule,
+ final String prefix, final int line) {
if (context == null) {
throw new YangParseException(currentModule.getName(), line, "Cannot find module with prefix '" + prefix
+ "'.");
return node;
}
- public static SchemaNodeBuilder findSchemaNodeInModule(final List<QName> pathToNode, final ModuleBuilder module) {
- List<QName> path = new ArrayList<>(pathToNode);
- QName first = path.remove(0);
+ /**
+ *
+ * Find a builder for node in data namespace of YANG module.
+ *
+ * Search is performed on full QName equals, this means builders and schema
+ * path MUST be resolved against imports and their namespaces.
+ *
+ * Search is done in data namespace, this means notification, rpc
+ * definitions and top level data definitions are considered as top-level
+ * items, from which it is possible to traverse.
+ *
+ *
+ * @param schemaPath
+ * Schema Path to node
+ * @param module
+ * ModuleBuilder to start lookup in
+ * @return Node Builder if found, {@link Optional#absent()} otherwise.
+ */
+ public static Optional<SchemaNodeBuilder> findSchemaNodeInModule(final SchemaPath schemaPath,
+ final ModuleBuilder module) {
+ Iterator<QName> path = schemaPath.getPathFromRoot().iterator();
+ Preconditions.checkArgument(path.hasNext(), "Schema Path must contain at least one element.");
+ QName first = path.next();
+ Optional<SchemaNodeBuilder> currentNode = getDataNamespaceChild(module, first);
- SchemaNodeBuilder node = module.getDataChildByName(first.getLocalName());
- if (node == null) {
- Set<NotificationBuilder> notifications = module.getAddedNotifications();
- for (NotificationBuilder notification : notifications) {
- if (notification.getQName().getLocalName().equals(first.getLocalName())) {
- node = notification;
- }
+ while (currentNode.isPresent() && path.hasNext()) {
+ currentNode = findDataChild(currentNode.get(), path.next());
+ }
+ return currentNode;
+ }
+
+ private static Optional<SchemaNodeBuilder> findDataChild(SchemaNodeBuilder parent, QName child) {
+ if (parent instanceof DataNodeContainerBuilder) {
+ return castOptional(SchemaNodeBuilder.class,
+ findDataChildInDataNodeContainer((DataNodeContainerBuilder) parent, child));
+ } else if (parent instanceof ChoiceBuilder) {
+ return castOptional(SchemaNodeBuilder.class, findCaseInChoice((ChoiceBuilder) parent, child));
+ } else if (parent instanceof RpcDefinitionBuilder) {
+ return castOptional(SchemaNodeBuilder.class, findContainerInRpc((RpcDefinitionBuilder) parent, child));
+
+ } else {
+ LOG.trace("Child {} not found in node {}", child, parent);
+ return Optional.absent();
+ }
+ }
+
+ /**
+ * Casts optional from one argument to other.
+ *
+ * @param cls
+ * Class to be checked
+ * @param optional
+ * Original value
+ * @return
+ */
+ private static <T> Optional<T> castOptional(Class<T> cls, Optional<?> optional) {
+ if (optional.isPresent()) {
+ Object value = optional.get();
+ if (cls.isInstance(value)) {
+ @SuppressWarnings("unchecked")
+ // Actually checked by outer if
+ T casted = (T) value;
+ return Optional.of(casted);
}
}
- if (node == null) {
- Set<RpcDefinitionBuilder> rpcs = module.getAddedRpcs();
- for (RpcDefinitionBuilder rpc : rpcs) {
- if (rpc.getQName().getLocalName().equals(first.getLocalName())) {
- node = rpc;
- }
+ return Optional.absent();
+ }
+
+ /**
+ *
+ * Gets input / output container from {@link RpcDefinitionBuilder} if QName
+ * is input/output.
+ *
+ *
+ * @param parent
+ * RPC Definition builder
+ * @param child
+ * Child QName
+ * @return Optional of input/output if defined and QName is input/output.
+ * Otherwise {@link Optional#absent()}.
+ */
+ private static Optional<ContainerSchemaNodeBuilder> findContainerInRpc(RpcDefinitionBuilder parent, QName child) {
+ if (INPUT.equals(child.getLocalName())) {
+ return Optional.of(parent.getInput());
+ } else if (OUTPUT.equals(child.getLocalName())) {
+ return Optional.of(parent.getOutput());
+ }
+ LOG.trace("Child {} not found in node {}", child, parent);
+ return Optional.absent();
+ }
+
+ /**
+ * Finds case by QName in {@link ChoiceBuilder}
+ *
+ *
+ * @param parent
+ * DataNodeContainer in which lookup should be performed
+ * @param child
+ * QName of child
+ * @return Optional of child if found.
+ */
+
+ private static Optional<ChoiceCaseBuilder> findCaseInChoice(ChoiceBuilder parent, QName child) {
+ for (ChoiceCaseBuilder caze : parent.getCases()) {
+ if (caze.getQName().equals(child)) {
+ return Optional.of(caze);
}
}
- if (node == null) {
- return null;
+ LOG.trace("Child {} not found in node {}", child, parent);
+ return Optional.absent();
+ }
+
+ /**
+ * Finds direct child by QName in {@link DataNodeContainerBuilder}
+ *
+ *
+ * @param parent
+ * DataNodeContainer in which lookup should be performed
+ * @param child
+ * QName of child
+ * @return Optional of child if found.
+ */
+ private static Optional<DataSchemaNodeBuilder> findDataChildInDataNodeContainer(DataNodeContainerBuilder parent,
+ QName child) {
+ for (DataSchemaNodeBuilder childNode : parent.getChildNodeBuilders()) {
+ if (childNode.getQName().equals(child)) {
+ return Optional.of(childNode);
+ }
+ }
+ LOG.trace("Child {} not found in node {}", child, parent);
+ return Optional.absent();
+ }
+
+ /**
+ *
+ * Find a child builder for node in data namespace of YANG module.
+ *
+ * Search is performed on full QName equals, this means builders and schema
+ * path MUST be resolved against imports and their namespaces.
+ *
+ * Search is done in data namespace, this means notification, rpc
+ * definitions and top level data definitions are considered as top-level
+ * items, from which it is possible to traverse.
+ *
+ *
+ * @param child
+ * Child QName.
+ * @param module
+ * ModuleBuilder to start lookup in
+ * @return Node Builder if found, {@link Optional#absent()} otherwise.
+ */
+ private static Optional<SchemaNodeBuilder> getDataNamespaceChild(ModuleBuilder module, QName child) {
+ /*
+ * First we do lookup in data tree, if node is found we return it.
+ */
+ final Optional<SchemaNodeBuilder> dataTreeNode = getDataChildByQName(module, child);
+ if (dataTreeNode.isPresent()) {
+ return dataTreeNode;
+ }
+
+ /*
+ * We lookup in notifications
+ */
+ Set<NotificationBuilder> notifications = module.getAddedNotifications();
+ for (NotificationBuilder notification : notifications) {
+ if (notification.getQName().equals(child)) {
+ return Optional.<SchemaNodeBuilder> of(notification);
+ }
}
- if (!path.isEmpty()) {
- node = findSchemaNode(path, node);
+ /*
+ * We lookup in RPCs
+ */
+ Set<RpcDefinitionBuilder> rpcs = module.getAddedRpcs();
+ for (RpcDefinitionBuilder rpc : rpcs) {
+ if (rpc.getQName().equals(child)) {
+ return Optional.<SchemaNodeBuilder> of(rpc);
+ }
}
+ LOG.trace("Child {} not found in data namespace of module {}", child, module);
+ return Optional.absent();
+ }
- return node;
+ private static Optional<SchemaNodeBuilder> getDataChildByQName(DataNodeContainerBuilder builder, QName child) {
+ for (DataSchemaNodeBuilder childNode : builder.getChildNodeBuilders()) {
+ if (childNode.getQName().equals(child)) {
+ return Optional.<SchemaNodeBuilder> of(childNode);
+ }
+ }
+ LOG.trace("Child {} not found in node {}", child, builder);
+ return Optional.absent();
}
/**
* path to augment target
* @return true if augmentation process succeed, false otherwise
*/
- public static boolean processAugmentation(final AugmentationSchemaBuilder augment, final ModuleBuilder firstNodeParent) {
- List<QName> path = augment.getTargetPath().getPath();
- Builder targetNode = findSchemaNodeInModule(path, firstNodeParent);
- if (targetNode == null) {
+ public static boolean processAugmentation(final AugmentationSchemaBuilder augment,
+ final ModuleBuilder firstNodeParent) {
+ Optional<SchemaNodeBuilder> potentialTargetNode = findSchemaNodeInModule(augment.getTargetNodeSchemaPath(),
+ firstNodeParent);
+ if (!potentialTargetNode.isPresent()) {
return false;
}
-
+ SchemaNodeBuilder targetNode = potentialTargetNode.get();
fillAugmentTarget(augment, targetNode);
+ Preconditions.checkState(targetNode instanceof AugmentationTargetBuilder,
+ "Node refered by augmentation must be valid augmentation target");
((AugmentationTargetBuilder) targetNode).addAugmentation(augment);
augment.setResolved(true);
return true;
}
}
- public static IdentitySchemaNodeBuilder findIdentity(final Set<IdentitySchemaNodeBuilder> identities, final String name) {
+ public static IdentitySchemaNodeBuilder findIdentity(final Set<IdentitySchemaNodeBuilder> identities,
+ final String name) {
for (IdentitySchemaNodeBuilder identity : identities) {
if (identity.getQName().getLocalName().equals(name)) {
return identity;
return parentModule;
}
- public static Set<DataSchemaNodeBuilder> wrapChildNodes(final String moduleName, final int line, final Set<DataSchemaNode> nodes,
- final SchemaPath parentPath, final URI ns, final Date rev, final String pref) {
+ public static Set<DataSchemaNodeBuilder> wrapChildNodes(final String moduleName, final int line,
+ final Set<DataSchemaNode> nodes, final SchemaPath parentPath, final URI ns, final Date rev,
+ final String pref) {
Set<DataSchemaNodeBuilder> result = new HashSet<>();
for (DataSchemaNode node : nodes) {
return result;
}
- public static DataSchemaNodeBuilder wrapChildNode(final String moduleName, final int line, final DataSchemaNode node,
- final SchemaPath parentPath, final QName qname) {
+ public static DataSchemaNodeBuilder wrapChildNode(final String moduleName, final int line,
+ final DataSchemaNode node, final SchemaPath parentPath, final QName qname) {
final SchemaPath schemaPath = parentPath.createChild(qname);
}
}
- public static Set<GroupingBuilder> wrapGroupings(final String moduleName, final int line, final Set<GroupingDefinition> nodes,
- final SchemaPath parentPath, final URI ns, final Date rev, final String pref) {
+ public static Set<GroupingBuilder> wrapGroupings(final String moduleName, final int line,
+ final Set<GroupingDefinition> nodes, final SchemaPath parentPath, final URI ns, final Date rev,
+ final String pref) {
Set<GroupingBuilder> result = new HashSet<>();
for (GroupingDefinition node : nodes) {
QName qname = new QName(ns, rev, pref, node.getQName().getLocalName());
return result;
}
- public static Set<TypeDefinitionBuilder> wrapTypedefs(final String moduleName, final int line, final DataNodeContainer dataNode,
- final SchemaPath parentPath, final URI ns, final Date rev, final String pref) {
+ public static Set<TypeDefinitionBuilder> wrapTypedefs(final String moduleName, final int line,
+ final DataNodeContainer dataNode, final SchemaPath parentPath, final URI ns, final Date rev,
+ final String pref) {
Set<TypeDefinition<?>> nodes = dataNode.getTypeDefinitions();
Set<TypeDefinitionBuilder> result = new HashSet<>();
for (TypeDefinition<?> node : nodes) {
}
public static List<UnknownSchemaNodeBuilder> wrapUnknownNodes(final String moduleName, final int line,
- final List<UnknownSchemaNode> nodes, final SchemaPath parentPath, final URI ns, final Date rev, final String pref) {
+ final List<UnknownSchemaNode> nodes, final SchemaPath parentPath, final URI ns, final Date rev,
+ final String pref) {
List<UnknownSchemaNodeBuilder> result = new ArrayList<>();
for (UnknownSchemaNode node : nodes) {
QName qname = new QName(ns, rev, pref, node.getQName().getLocalName());
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import java.io.*;
-import java.util.*;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import org.junit.Test;
import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
fail("YangParseException should by thrown");
}
} catch (YangParseException e) {
- String expected = "Error in module 'augment1' at line 10: Failed to perform augmentation: Error in module 'augment0' at line 8: Can not add 'leaf id' to 'container bar' in module 'augment0': node with same name already declared at line 9";
- assertEquals(expected, e.getMessage());
+ assertTrue(e.getMessage().contains("Error in module 'augment1'"));
+ assertTrue(e.getMessage().contains("Failed to perform augmentation:"));
+
}
}
fail("YangParseException should by thrown");
}
} catch (YangParseException e) {
- String expected = "Error in module 'augment0' at line 17: Can not add 'anyxml delta' to node 'choice-ext' in module 'augment0': case with same name already declared at line 18";
- assertEquals(expected, e.getMessage());
+ assertTrue(e.getMessage().contains("Error in module "));
+ assertTrue(e.getMessage().contains("case with same name already declared "));
}
}
namespace "urn:simple.augment0.demo";
prefix "a0";
+ revision "2014-06-02";
+
container foo {
description "foo container";
container bar {
module augment1 {
yang-version 1;
- namespace "urn:simple.augment0.demo";
+ namespace "urn:simple.augment1.demo";
prefix "a1";
+
import augment0 {
prefix "a0";
}
+ revision "2014-06-02";
+
+ augment "/a0:foo/a0:bar" {
+ leaf id {
+ type string;
+ }
+ }
+
augment "/a0:foo/a0:bar" {
leaf id {
type string;
prefix "a0";
}
+ revision "2014-06-02";
+
+ augment "/a0:foo/a0:bar/a0:choice-ext" {
+ anyxml delta;
+ }
+
augment "/a0:foo/a0:bar/a0:choice-ext" {
anyxml delta;
}